HDU 6214 Smallest Minimum Cut (最小割最小割边)(两种算法的分析)

来源:互联网 发布:圣戈班上海待遇知乎 编辑:程序博客网 时间:2024/06/05 15:37

Problem Description
Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition of nodes set V into two parts such that s and t belong to different parts. The cut set is the subset of E with all edges connecting nodes in different parts. A minimum cut is the one whose cut set has the minimum summation of capacities. The size of a cut is the number of edges in the cut set. Please calculate the smallest size of all minimum cuts.

Input
The input contains several test cases and the first line is the total number of cases T (1≤T≤300).
Each case describes a network G, and the first line contains two integers n (2≤n≤200) and m (0≤m≤1000) indicating the sizes of nodes and edges. All nodes in the network are labelled from 1 to n.
The second line contains two different integers s and t (1≤s,t≤n) corresponding to the source and sink.
Each of the next m lines contains three integers u,v and w (1≤w≤255) describing a directed edge from node u to v with capacity w.

Output
For each test case, output the smallest size of all minimum cuts in a line.

Sample Input
2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 3

Sample Output
2
3

Source
2017 ACM/ICPC Asia Regional Qingdao Online

无语自己,比赛结束一打代码就过了,裸的最小割最小割边
这里写图片描述

用的第一种,比赛时用第二种一直超时和WA,哎!
对于第一种算法:
最小割最小割边的 建边的时候每条边权 w = w * (E + 1) + 1; //加上1之后跑出来的最大流必定是变数最小的。
这样得到的最大流为max_flow/(E+1),因为即使所以的边都算上,也只是多个E,那么除以(E+1)是完全不影响的,而最小的割边数是max_flow % (E+1) 即把全部的1
算上也只有E,对E+1取余后就是最小的变数

而第二种算法,可以过HDU3987 但其实是一种错误的算法,在有些情况时跑出来的不是最小边,如下图,某位大神给我找到的反例,这个图就可以搞掉第二种算法,不过如果是用链式前向星存图的话,可能是走1000那条边的,就再修改一下:
这里写图片描述
红线代表满流边,如果按照第二种算法的话得到的是2,而实际是4.

#include<iostream>#include<cstring>#include<cmath>#include<vector>#include<string>#include<queue>#include<algorithm>using namespace std;const int MAX_V = 210;const int MAX_E = 3010;const int INF = 0x3f3f3f3f;int V,E;struct Edge{    int to,cap,rev;};vector<Edge> G[MAX_V];int level[MAX_V],iter[MAX_V];void add(int u,int v,int cap){    G[u].push_back((Edge){v,cap*(E+1)+1,(int)G[v].size()});    G[v].push_back((Edge){u,0,(int)G[u].size()-1});}void bfs(int s){    memset(level,-1,sizeof(level));    queue<int> q;    level[s] = 0;    q.push(s);    while(!q.empty()){        int v = q.front();q.pop();        for(int i=0;i<G[v].size();i++){            Edge &e = G[v][i];            if(e.cap > 0 && level[e.to] < 0){                level[e.to] = level[v] + 1;                q.push(e.to);            }        }    }}int dfs(int s,int t,int f){    if(s == t)  return f;    for(int &i = iter[s];i < G[s].size();i++){        Edge &e = G[s][i];        if(e.cap > 0 && level[s] < level[e.to]){            int d = dfs(e.to,t,min(e.cap,f));            if(d > 0){                e.cap -= d;                G[e.to][e.rev].cap += d;                return d;            }        }    }    return 0;}int max_flow(int s,int t){    int res = 0;    while(true){        bfs(s);        if(level[t] < 0)    return res;        memset(iter,0,sizeof(iter));        int f = 0;        while((f = dfs(s,t,INF)) > 0)            res += f;    }}int main(void){    int t;    scanf("%d",&t);    while(t--){        scanf("%d %d",&V,&E);        for(int i=1;i<=V;i++)            G[i].clear();        int a,b;        scanf("%d %d",&a,&b);        int x,y,z;        for(int i=1;i<=E;i++){            scanf("%d %d %d",&x,&y,&z);            add(x,y,z);        }        int res = max_flow(a,b);        printf("%d\n",res % (E+1));    }    return 0;}
原创粉丝点击