HDU 3987 求断开两点最小花费下的边数 最小割

来源:互联网 发布:网络摄像头带宽计算 编辑:程序博客网 时间:2024/04/30 10:59

题意:

给定n个点m条边(点标从0开始)

下面m行 u v d(边权) k(k=0表示单向,1表示双向)

问:

把0 和 n-1点断开 使得0点无法到达n-1点 需要删去多少条边(删边的花费为边权) 问在最小花费情况下,输出要删的边数

 

思路:

最小割裸题,以0为源点,n-1为汇点,边权改为 w* E(E>最大的边权) +1

最后最大流%E,就可以得到边数。

注意用 __int64

#include <iostream>#include <string.h>#include<stdio.h>#include<queue>using namespace std;#define ll __int64#define inf 1152921504606846976#define N 1005#define M 100010//N为点数 M为边数struct Edge{int from, to;ll cap;int nex;}edge[M*8];//注意这个一定要够大 不然会re 还有反向弧int head[N], edgenum;void addedge(int u, int v, ll cap){Edge E = { u, v, cap, head[u]};edge[ edgenum ] = E;head[u] = edgenum ++;Edge E2= { v, u, 0,   head[v]};edge[ edgenum ] = E2;head[v] = edgenum ++;}int sign[N], s, t;bool BFS(int from, int to){memset(sign, -1, sizeof(sign));sign[from] = 0;queue<int>q;q.push(from);while( !q.empty() ){int u = q.front(); q.pop();for(int i = head[u]; i!=-1; i = edge[i].nex){int v = edge[i].to;if(sign[v]==-1 && edge[i].cap){sign[v] = sign[u] + 1, q.push(v);if(sign[to] != -1)return true;}}}return false;}int Stack[M*4], top, cur[M*4];ll dinic(){ll ans = 0;while( BFS(s, t) ){memcpy(cur, head, sizeof(head));int u = s;top = 0;while(1){if(u == t){ll flow = inf;int loc;//loc 表示 Stack 中 cap 最小的边for(int i = 0; i < top; i++)if(flow > edge[ Stack[i] ].cap){flow = edge[Stack[i]].cap;loc = i;}for(int i = 0; i < top; i++){edge[ Stack[i] ].cap -= flow;edge[Stack[i]^1].cap += flow;}ans += flow;top = loc;u = edge[Stack[top]].from;}for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].nex)//cur[u] 表示u所在能增广的边的下标if(edge[i].cap && (sign[u] + 1 == sign[ edge[i].to ]))break;if(cur[u] != -1){Stack[top++] = cur[u];u = edge[ cur[u] ].to;}else{if( top == 0 )break;sign[u] = -1;u = edge[ Stack[--top] ].from;}}}return ans;}int main() {int n, m, T, Cas = 1;scanf("%d",&T);int u, v, k;ll d;while (T--) {scanf("%d %d", &n, &m);memset(head, -1, sizeof(head));ll E = 100001;while(m--){scanf("%d %d %I64d %d",&u, &v, &d, &k); d*=E; d++;addedge(u, v, d); if(k) addedge(v, u, d);}s = 0, t = n-1;printf("Case %d: %I64d\n", Cas++, dinic()%E);}return 0;}/*994 50 1 3 00 2 1 01 2 1 11 3 1 12 3 3 16 70 1 1 00 2 1 00 3 1 01 4 1 02 4 1 03 5 1 04 5 2 03 60 1 1 00 1 2 01 1 1 11 2 1 01 2 1 02 1 1 1*/

0 0
原创粉丝点击