BZOJ 2521 最小生成树(最小割)
http://www.lydsy.com/JudgeOnline/problem.php?id=2521
题意:每次能增加一条边的权值1,求最小代价让一条边保证在最小生成树里
思路:如果两个点中有环,那么这条边必须不能是环的最大边,这样子把之前所有的边权值变成V+1-v[i],无向图网络流就可以了
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define inf 0x7fffffff 7 struct edge{ 8 int u,v,w; 9 }e[200005]; 10 int n,m,id,dis[200005],cnt[200005],tot,S,T,nodes; 11 int flow[200005],op[200005],next[200005],first[200005],go[200005]; 12 int read(){ 13 char ch=getchar();int t=0,f=1; 14 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 15 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 16 return t*f; 17 } 18 void insert(int x,int y,int z){ 19 tot++; 20 go[tot]=y; 21 next[tot]=first[x]; 22 first[x]=tot; 23 flow[tot]=z; 24 } 25 void add(int x,int y,int z){ 26 insert(x,y,z);op[tot]=tot+1; 27 insert(y,x,0);op[tot]=tot-1; 28 } 29 void add2(int x,int y,int z){ 30 insert(x,y,z);op[tot]=tot+1; 31 insert(y,x,z);op[tot]=tot-1; 32 } 33 int dfs(int x,int f){ 34 if (x==T) return f; 35 int mn=nodes,sum=0; 36 for (int i=first[x];i;i=next[i]){ 37 int pur=go[i]; 38 if (flow[i]&&dis[pur]+1==dis[x]){ 39 int save=dfs(pur,std::min(f-sum,flow[i])); 40 sum+=save; 41 flow[i]-=save; 42 flow[op[i]]+=save; 43 if (sum==f||dis[S]>=nodes) return sum; 44 } 45 if (flow[i]) mn=std::min(mn,dis[pur]); 46 } 47 if (sum==0){ 48 cnt[dis[x]]--; 49 if (cnt[dis[x]]==0){ 50 dis[S]=nodes; 51 }else{ 52 dis[x]=mn+1; 53 cnt[dis[x]]++; 54 } 55 } 56 return sum; 57 } 58 int main(){ 59 n=read();m=read();id=read(); 60 S=0,T=n+1;nodes=n+2; 61 for (int i=1;i<=m;i++){ 62 e[i].u=read();e[i].v=read();e[i].w=read(); 63 } 64 add(S,e[id].u,inf); 65 add(e[id].v,T,inf); 66 for (int i=1;i<=m;i++)if (i!=id&&e[i].w<=e[id].w){ 67 add2(e[i].u,e[i].v,e[id].w+1-e[i].w); 68 } 69 int ans=0; 70 while (dis[S]<nodes) ans+=dfs(S,inf); 71 printf("%d\n",ans); 72 }