1. 程式人生 > >UVA 11478 淺談差分約束SPFA判負環

UVA 11478 淺談差分約束SPFA判負環

這裡寫圖片描述
世界真的很大
圖論的演算法是個神奇東西
上次做了這道題就深有感觸了
差分約束也是個差不多的道理,spfa
先看下題吧:
description:

給定一個有向圖,邊有權值,每次操作指定一個點u,一個值d,使所有u的出邊+d,所有入邊-d。問經過數次操作後,最小正邊權最大為多少。如可以無限大就輸出Infinite,如不能為正就輸出No Solution

input

多組資料,輸入到EOF
每組資料第一行包含2個整數n(點),m(邊)
接下來m行每行包含3個整數u,v,w
表示u到v有一條邊權為w的邊

output

每組資料一個輸出表示答案

要求輸出最小的最大,自然想到二分答案
每次二分一個權值val,check能否找到一個方案使所有邊的權值大於val
考慮任意一個點,他的每條入邊和每條出邊的增加(減少)的量肯定是相同的,設為sumi
考慮一條邊(a,b),其操作之後的權值為w(a,b)+suma-sumb ,權值是大於val的,所以:
w(a,b)+suma-sumb > val
移相之後得到:
sumb-suma <= w(a,b)-val
sumb <= w(a,b)-val + suma
這就是差分約束的典型等式了
考慮SPFA中處理的等式
dis[v]< w(u,v) + dis[u]
不是有點相似嗎,這裡w(a,b)-val和w(u,v)都是一個固定的常量,像這樣的這一串式子就可以用像SPFA的方法處理它,如果SPFA能跑出來就說明跑出來了一組可行解,suma就是a點的dis值
如果跑不出來,說明有負環,說明找不到一組可行解
那對於sumb <= w(a,b)-val + suma
我們就連一條a到b,權值為w(a,b)-val的邊,SPFA需要一個源點,因為是單源最短路嘛,所以我們就加一個無關緊要的源點S,使其與所有點連邊,邊權為0
題目規定了上界,所以只要判一下val為最上界是否滿足有解,如果是,就輸出Infinite
題目規定為正數,所以判一下下界1,如果都不行,無解的話就輸出No Solution
完整程式碼:

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;

struct edge
{
    int v,last,w;
}ed[100010];

queue <int> state;

int head[100010],dis[100010],se[100010],book[100010];
int n,m,ans,num=0,S=0,big=0;

void init()
{
    num=0
,ans=0,S=0,big=0; memset(head,0,sizeof(head)); } void add(int u,int v,int w) { num++; ed[num].v=v; ed[num].w=w; ed[num].last=head[u]; head[u]=num; } bool SPFA() { memset(book,0,sizeof(book)); memset(dis,0x3f3f3f3f,sizeof(dis)); memset(se,0,sizeof(se)); while(!state.empty()) state.pop(); state.push(S); se[S]=1
,dis[S]=0,book[S]=1; while(!state.empty()) { int u=state.front(); se[u]=0;state.pop(); for(int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if(dis[v]>dis[u]+ed[i].w) { dis[v]=dis[u]+ed[i].w; if(!se[v]) { se[v]=1; state.push(v); book[v]++; if(book[v]>n+1) return 0; } } } } return 1; } bool check(int val) { bool flag; for(int i=1;i<=num;i++) ed[i].w-=val; flag=SPFA(); for(int i=1;i<=num;i++) ed[i].w+=val; return flag; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); big=max(big,w); } for(int i=1;i<=n;i++) add(S,i,0); if(check(big+1)) { printf("Infinite\n"); continue ; } else if(!check(1)) { printf("No Solution\n"); continue ; } int lf=1,rg=big; while(lf<=rg) { int mid=(lf+rg)>>1; if(check(mid)) { ans=mid; lf=mid+1; } else rg=mid-1; } printf("%d\n",ans); } } /* Whoso pulleth out this sword from this stone and anvil is duly born King of all England */

嗯,就是這樣

相關推薦

UVA 11478 約束SPFA

世界真的很大 圖論的演算法是個神奇東西 上次做了這道題就深有感觸了 差分約束也是個差不多的道理,spfa 先看下題吧: description: 給定一個有向圖,邊有權值,每次操作指定一個點u,一個值d,使所有u的出邊+d,所有入邊-d。問經

poj 1364(約束+spfa判斷)

King Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12458 Accepted: 4524 Description Once, in one kingdom, there was a

洛谷P3275 [SCOI2011]糖果_約束_

Code: #include<cstdio> #include<queue> #include<algorithm> using namespace std; const int N=300000+3; const int I

約束問題

最短 HR .html 求解 不難 pos 表示 聯想 html 差分約束 差分約束是解決這樣一類問題 給出\(n\)個形如\(x[j]-x[i]<=k\)的式子,求\(x[n]-x[1]\)的最大/最小值 思路 其實這個問題是挺套路的 我們把給出的式子變一下 \(x

約束系統

差分約束系統是個啥呢?可能看名字非常地難理解,其實它要求的就是一個**n元一次不等式組的解**,形式如下: $\begin{cases}x-y \leq 10\\y-z \leq 5\\\end{cases}$ 那麼求解這一組資料的解,就是差分約束系統的目的 那麼對於以上這一個用數學方式來求解的不等

[洛谷 P1993]小K的農場 --- 約束 + spfa

傳送門:洛谷 P1993 題目描述 小 K K K在

ZOJ 2770 約束+SPFA

最大值 multiple sample mea tro output problem igp data Burn the Linked CampTime Limit: 2 Seconds Memory Limit: 65536 KB It is well know

POJ 3159 Candies(約束+spfa+鏈式前向星)

void tdi div con pre ace != view ash 題目鏈接:http://poj.org/problem?id=3159 題目大意:給n個人派糖果,給出m組數據,每組數據包含A,B,C三個數,意思是A的糖果數比B少的個數不多於C,即B的糖果數 -

POJ 1364 / HDU 3666 【約束-SPFA

題意 最短 false nbsp DG bsp ont class ast POJ 1364 題解:最短路式子:d[v]<=d[u]+w 式子1:sum[a+b+1]−sum[a]>c — sum[a]<

HDU 1384 Intervals【約束-SPFA

入隊 數組 spf 反向 mem set pac 最大值 can 類型:給出一些形如a−b<=k的不等式(或a−b>=k或a−b<k或a−b>k等),問是否有解【是否有負環】或求差的極值【最短/長路徑】

poj 1201 Intervals【約束+spfa

相反數 ons 最長 using cpp val 註意 interval space 設s為前綴和,首先顯然的條件是\[ s_{bi}-s_{ai-1}>=c \],然後隱含的是\[ s_i-s_{i-1}>=0 s_i-s_{i-1}<=1 \] 然後根

Poj 3169 Layout【約束+SPFA

Layout Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10278 Accepted: 4946 Description Like everyone els

POJ 3169 Layout 約束+spfa

Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows nu

POJ 1201 約束+SPFA

思路: 差分約束,難在建圖。(我是不會告訴你我剛學會SPFA的。。。) 把每個區間的ai–>bi連一條長度為ci的邊。 k–>k+1連一條長度為0的邊。 k+1–>k連一條長度

poj 1364 King(線性約束+超級源點+spfa

King Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14791 Accepted: 5226 Description Once, in one kingdom, there was a queen and that queen

poj3169 約束+spfa

題目連結在這裡 題目大意是有N頭牛,有的牛喜歡相互捱得近一點,有的想相互離得遠一點。輸入的第一行給出三個數N, ML, MD,分別代表N頭牛,有ML條資料是離得近一點,MD條資料是離得遠一點。接下來有ML + MD條資料,每條資料有a b c三個數,代表牛a和牛b離得不超過(或者最少是)c。問第

UVA 558 Wormholes 【SPFA

math.h struct possible sta clas ack names dsm 推斷 題目鏈接: https://uva.onlinejudge.org

POJ-1860 Currency Exchange 【spfa

exchange call ant 代碼 while sim api where class Description Several currency exchange points are working in our city. Let us suppose that

洛谷P3385 【模板】 DFS-SPFA 圖論

string inf scan space can 清空 span %d pre 洛谷P3385 【模板】負環 圖論 今天get了 一個 DFS-SPFA 判負環的方法 一般的 BFS-SPFA 判負環 一般就是 不停地做,如果某點第 n+1次加入隊列中,那麽說明這個圖存在

[poj3259]Wormholes(spfa)

隊列 spfa算法 oid math num nbsp poj3259 pre ash 題意:有向圖判負環。 解題關鍵:spfa算法+hash判負圈。 負圈是指圈上的總和小於0 #include<cstdio> #include<cstring