残量改为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\n",casenum,ans);
casenum++;
}
return 0;
}