1. 程式人生 > >hdu 3987 求割邊最少的最小割

hdu 3987 求割邊最少的最小割

http://acm.hdu.edu.cn/showproblem.php?pid=3987
割邊必然是滿流的邊
方法一:
重新建圖,將滿流的邊改為容量為1,非滿流的邊改為容量為INF。再跑一邊最大流就是割邊的個數。
(要注意的是,改圖的時候,應該對正向邊進行判斷,cap == 0則為滿流)
方法二:
建圖時,每條邊的cap = cap*(E+1) + 1,則最後的最小割就是max_flow / (E+1) ,割邊的個數就是max_flow%(E+1)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> #include <vector> #include <queue> #include <stack> using namespace std; const int M_node = 1090,M_edge = 500009,INF = 0x3f3f3f3f; struct edge { int to,cap,next; bool is_rev; }edge[M_edge],edge2[M_node]; int head[M_node],level[M_node]; int pre[M_node]; int
tot; int n,m; int s,t; int ss,tt; int vis[M_node]; void init() { memset(head,-1,sizeof(head)); tot = 0; memset(vis,0,sizeof(vis)); } void add_edge(int u,int v,int cap) { edge[tot].to = v;edge[tot].cap = cap;edge[tot].is_rev = false;edge[tot].next = head[u];head[u] = tot++; edge[tot].to = u;edge[tot].cap = 0
;edge[tot].is_rev = true;edge[tot].next = head[v];head[v] = tot++; } bool bfs(int s,int t) { memset(level,-1,sizeof(level)); level[s] = 0; queue<int> q; q.push(s); while(!q.empty()) { int v = q.front(); q.pop(); for(int i = head[v];i != -1;i = edge[i].next) { int u = edge[i].to; if(level[u] < 0 && edge[i].cap > 0) { level[u] = level[v] + 1; q.push(u); } } } return level[t] != -1; } int dfs(int v,int t,int f) { if(v == t) return f; for(int &i = pre[v];i != -1;i = edge[i].next) { int u = edge[i].to; if(level[u] > level[v] && edge[i].cap > 0) { int d = dfs(u,t,min(f,edge[i].cap)); if(d > 0) { edge[i].cap -= d; edge[i^1].cap += d; //pre[v] = i; //printf("i = %d,v = %d,u = %d, d = %d\n",i,v,u,d); //printf("edge[i].cap = %d\n",edge[i].cap); return d; } } } level[v] = -1; return 0; } int max_flow(int s,int t) { int flow = 0; while(bfs(s,t)) { for(int i = 0;i <= t;i++) pre[i] = head[i]; int f = 0; while((f = dfs(s,t,INF)) > 0) flow += f; } return flow; } int main() { int T; scanf("%d",&T); int kas = 1; while(T--) { scanf("%d%d",&n,&m); init(); for(int i = 0;i < m;i++) { int u,v,cost,b; scanf("%d%d%d%d",&u,&v,&cost,&b); if(b) { add_edge(u,v,cost); add_edge(v,u,cost); } else add_edge(u,v,cost); } s = n; t = n + 1; add_edge(s,0,INF); add_edge(n-1,t,INF); int ans = max_flow(s,t); //printf("debug ---- ans = %d\n",ans); for(int i = 0;i < n;i++) { for(int j = head[i];j != -1;j = edge[j].next) { if(edge[j].cap == 0 && edge[j].is_rev == false) { edge[j].cap = 1; edge[j^1].cap = 0; //add_edge(t+1+i,t+1+edge[j].to,1); //printf("add_edge u = %d,v = %d\n",i,edge[j].to); } else if(edge[j].is_rev == false) { edge[j].cap = INF; edge[j^1].cap = 0; } //add_edge(t+1+i,t+1+edge[j].to,INF); } } ans = max_flow(s,t); printf("Case %d: %d\n",kas++,ans); } return 0; }