这题是求割边最小的最小割问题,我们要了解两个性质,一个是最小割边一定满流,满流的不一定是最小割边。还有一个就是最大流等于最小割。
我们先求一遍最大流,这时满流的就可能是最小割边,我们要求最少有多少条边,就相当于求最小割就可以转换成求最大流,也就是把满流的那条边的容量设为1,其他的设为无穷,这时最大流的值也就是最小割的值就等于最小割边数(因为最小割就相当于最小割去多少容量,而1容量就代表一条边)。
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=1100;
const int maxm=500000+10;
const int INF=0x3f3f3f3f;
int min(int x,int y)
{
if(x<y)
return x;
else
return y;
}
struct node {
int u, v, cap, flow, next;
};
node edge[maxm];
int dist[maxn], head[maxn], cur[maxn];
bool vis[maxn];
int cnt;
void init(){
cnt = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w){
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].cap=w;
edge[cnt].flow=0;
edge[cnt].next=head[u];
head[u] = cnt++;
edge[cnt].u=v;
edge[cnt].v=u;
edge[cnt].cap=0;
edge[cnt].flow=0;
edge[cnt].next=head[v];
head[v] = cnt++;
}
bool BFS(int st, int ed){
queue<int>q;
memset(vis, 0 ,sizeof(vis));
memset(dist, -1, sizeof(dist));
q.push(st);
dist[st] = 0;
vis[st] = 1;
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = head[u]; i != -1; i = edge[i].next){
node E = edge[i];
if(!vis[E.v] && E.cap > E.flow){
vis[E.v] = 1;
dist[E.v] = dist[u] + 1;
if(E.v == ed) return true;
q.push(E.v);
}
}
}
return false;
}
int DFS(int x, int ed, int a){
if(a == 0 || x == ed)
return a;
int flow = 0, f;
for(int &i = cur[x]; i != -1; i = edge[i].next){
node &E = edge[i];
if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){
E.flow += f;
edge[i ^ 1].flow -= f;
a -= f;
flow += f;
if(a == 0) break;
}
}
return flow;
}
int maxflow(int st, int ed){
int flow = 0;
while(BFS(st, ed)){
memcpy(cur, head, sizeof(head));
flow += DFS(st, ed, INF);
}
return flow;
}
int main()
{
int t,icase;
scanf("%d",&t);
for(icase=1;icase<=t;icase++)
{
init();
int n,m;
scanf("%d%d",&n,&m);
int i,j;
for(i=0;i<m;i++)
{
int u,v,c,d;
scanf("%d%d%d%d",&u,&v,&c,&d);
add(u,v,c);
if(d==1)
add(v,u,c);
}
maxflow(0,n-1);
for(i=0;i<cnt;i+=2)
{
if(edge[i].cap==edge[i].flow)
{
edge[i].cap=1;
edge[i].flow=0;
edge[i^1].cap=0;
edge[i^1].flow=0;
}
else
{
edge[i].cap=INF;
edge[i].flow=0;
edge[i^1].cap=0;
edge[i^1].flow=0;
}
}
int ans=maxflow(0,n-1);
printf("Case %d: %d\n",icase,ans);
}
return 0;
}