題意: 給出有n 個節點的網路,和m條單向邊,知道了每條邊的容量,問哪些邊滿足增加該邊的容量後,能使得從起點到終點的總流量增加(只能修改一條邊!)。
注意一點,在一條流路中只能修改一條,好像s->1->2->t,假設每條邊的容量都是2,那麼最大流的流路只有一條,但是這條流路中,
要想增大一條邊的容量而使整個網路的最大流增加是不行的,一定要把所有邊容量都增大,這與題意不符,所以這個case輸出是0,表示1條都沒有
那麼題目就轉化成了在求最大流後的殘流網路中求這樣的乙個滿流邊集x-y(邊的容量為0),使得如果在殘餘網路中存在路徑[s,x]和[y,t],該邊集的邊的條數即為所求。找滿流邊集很容量,關鍵是判斷這個滿流邊集中的邊兩端點i,j,使i能由s到達且j能達到t。那麼可以對s進行一次dfs(能夠聯通的點標記在v1中),然後將圖反向後再從t dfs一遍(能夠聯通的點標記在v2中)。那麼對於滿流集合中任意一條有向邊i->j,如果v1[i]和v2[j]均標記過,則滿足上述性質,為題中所求的邊中的一條。
#include#include#include#include#include#include#include#include#include #include#includeusing namespace std ;
const int n=600 ;
const int m=100000;
const int inf=1<<30 ;
struct node
edge[m];
int head[n],cur[n],dis[n],gap[n],pre[n];
int top ,g[n][n],v1[n],v2[n];
int n,m;
void add(int u ,int v,int c)
void sap(int s,int t ,int nv)
flow += minflow ;
minflow = inf ;
}
goto loop ;
}
}
int mindis=nv ;
for(int i = head[u] ; i!=-1 ; i=edge[i].next)
}
if(--gap[dis[u]]==0) break ;
gap[ dis[u] = mindis +1 ]++ ;
u=pre[u] ;
}
}
void dfs1(int u)
}void dfs2(int u)
}int main()
sap(s,t,n);
memset(g,0,sizeof(g)) ;
for(int i = 0 ; i < top ; i=i+2)
dfs1(s) ;
memset(g,0,sizeof(g)) ;
for(int i = 0 ; i < top ; i=i+2)
dfs2(t) ;
int ans = 0;
for(int i = 0 ; i < top ; i=i+2)
printf("%d\n",ans);
}return 0;
}
POJ 3204 網路流的必須邊
思路 求一遍網路流 在殘餘網路上dfs 從起點dfs 從終點把邊反向dfs 乙個邊跟起點連通 跟終點反向的邊連通 ans 注 此題不能用tarjan 因為有邊權為0的邊 by siriusren include include include include using namespace std ...
poj 1815(最小割 割集)
思路 題目要求是剔除多少個點,可以將其轉化為剔除多少條邊,因此需要拆點,將點i拆成i,i n,便容量為1,表示每個人起的傳遞作用只能是一次。然後就是列舉了,刪除某條邊,如果求出的最小割比原來的要小,說明減少的是割邊集。1 include2 include3 include4 include5 inc...
最小割連邊模型
1.對於兩個都有s方面的邊和t方面的邊的點,在他們之間連inf表示這兩個點要麼全割s方面的邊要麼都割t方面的邊。最小割的一種數學建模 01 變數建模 連邊 對於乙個 01 變數 a 它在圖中的點的編號我們也記作 a 邊 s,a,b 表示 a 1 時要花費 b 的代價。邊 a,t,b 表示 a 0 時...