CDQZ多校集訓題目--盛夏
阿新 • • 發佈:2018-12-12
題意:
給一個有向無環帶權圖,每條路徑上最多隻能割一條邊,最後使1到n無路徑,問最小割邊邊權和是多少。
題意很清楚,但是這道題的題解其實是隻適用於很少的情況的
我們考慮的做法是網路流最小割
對於所有邊的反向邊,流量均為inf
那麼如果具體分析原因其實是這條路徑割上游,那條路徑割下游,然而可以走這條路徑的上游和那條路徑的下游,如何避免?
考慮到那條路徑的上游和這條路徑的下游是沒有割的,中間的邊如果可以反著走那麼就可以很好的避免這種情況的發生
所以如果反向邊是inf就可以很好的解決這個問題了
但是這樣子想未必太過美好了一點,例如:
如果在網路流的圖中有一條邊是反向建的,那麼正向的流量就是inf,導致答案與正確答案不符
無論如何,這道題的思路還是很好的,下貼程式碼
#include<bits/stdc++.h> using namespace std; const int inf=0x7fffffff; int tot=1,w[2005],remain[2005],to[2005],nxt[2005]; int head[305],depth[305],hh[305]; int n,m,shu1,shu2,shu3,ans; queue <int> que; int minn(int x,int y) { if(x<y) return x; return y; } void add(int x,int y,int z) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; remain[tot]=z; } bool bfs() { que.push(1); memset(depth,0,sizeof(depth)); depth[1]=1; while(!que.empty()) { int x=que.front(); que.pop(); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(!remain[i]||depth[y]) continue; depth[y]=depth[x]+1; que.push(y); } } return depth[n]; } int dfs(int x,int delta) { if(x==n) return delta; int sum=0; for(int &i=hh[x];i&δi=nxt[i]) { int y=to[i]; if(depth[y]!=depth[x]+1||!remain[i]) continue; int flow=minn(remain[i],dfs(y,delta)); remain[i]-=flow; remain[i^1]+=flow; sum+=flow; delta-=flow; } return sum; } int main() { freopen("mer.in","r",stdin); freopen("mer.out","w",stdout); cin>>n>>m; for(int i=1;i<=m;i++) { scanf("%d%d%d",&shu1,&shu2,&shu3); add(shu1,shu2,shu3); add(shu2,shu1,inf/3); } while(bfs()) { for(int i=1;i<=n;i++) hh[i]=head[i]; ans+=dfs(1,inf); } cout<<ans; return 0; }