残量改为1,其他边残量改为无穷,则再跑一次最大流,所得即为答案。(思,最小割有喝多组,但是要割边数量最少
的,那么把满流的流量改为1,再跑一次最大流即可)。
未1A原因:
1*:添加边的时候,把双向边添加为一条(反向的流量上限==正向),这样不是不可以,但是由于后面用到要取有效边
(非后悔边,边编号比为偶数),导致错误,改为添加俩次即可。
2//:数据较大,总流量10W*1000,可能暴int。
#include<iostream> //98ms #include<cstdio> #include<queue> using namespace std; long long e[400001][3];int head[1100];const int inf=0x3f3f3f3f; int n,m;int nume; void addedge(int from,int to,int w,int derect) //添加边的函数,derect为1时要添加双向边 { e[nume][0]=to; e[nume][1]=head[from];head[from]=nume; e[nume++][2]=w; e[nume][0]=from; e[nume][1]=head[to];head[to]=nume; e[nume++][2]=0; if(derect==1) { e[nume][0]=from; e[nume][1]=head[to];head[to]=nume; e[nume++][2]=w; e[nume][0]=to; e[nume][1]=head[from];head[from]=nume; e[nume++][2]=0; } } int level[1100];int vis[1100]; bool bfs() //dinic { for(int i=0;i<=n;i++) vis[i]=level[i]=0; queue<int>q;q.push(0); vis[0]=1; while(!q.empty()) { int cur=q.front();q.pop(); for(int i=head[cur];i!=-1;i=e[i][1]) { int v=e[i][0]; if(!vis[v]&&e[i][2]>0) { level[v]=level[cur]+1; if(v==n-1)return 1; vis[v]=1; q.push(v); } } } return vis[n-1]; } long long dfs(int u,long long minf) { if(u==n-1||minf==0)return minf; long long sumf=0,f; for(int i=head[u];i!=-1&&minf;i=e[i][1]) { int v=e[i][0]; if(level[v]==level[u]+1&&e[i][2]>0) { f=dfs(v,minf<e[i][2]?minf:e[i][2]); e[i][2]-=f;e[i^1][2]+=f; minf-=f;sumf+=f; } } return sumf; } long long dinic() { long long sum=0; while(bfs()) { sum+=dfs(0,inf); } return sum; } long long getmincut() { long long cutedge=0; for(int i=0;i<=n;i++) vis[i]=0; queue<int>q;q.push(0);vis[0]=1; while(!q.empty()) { int cur=q.front();q.pop(); for(int i=head[cur];i!=-1;i=e[i][1]) { int v=e[i][0]; if(i%2==0&&e[i][2]==0) //边数偶数的边是残量网络有效边(非后悔边) { e[i][2]=1;e[i^1][2]=0;} else if(i%2==0&&e[i][2]>0) {e[i][2]=inf;e[i^1][2]=0;} if(!vis[v]&&e[i][2]>=0) { vis[v]=1;q.push(v); } } } cutedge=dinic(); return cutedge; } int main() { int N;scanf("%d",&N); int casenum=1; while(N--) { scanf("%d%d",&n,&m); nume=0; for(int i=0;i<=n;i++) head[i]=-1; for(int i=0;i<m;i++) { int from,to,w,d; scanf("%d%d%d%d",&from,&to,&w,&d); addedge(from,to,w,d); } dinic(); long long ans=getmincut(); printf("Case %d: %lld ",casenum,ans); casenum++; } return 0; }