[HDU6214] Smallest Minimum Cut (最小割)

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.

题意:求最少边的最小割
添加边的时候流量改为w*(m + 1) + 1,跑一遍最大流flow,最小割为flow/(m+1),最少的最小割边数为flow%(m+1)

把边扩大m+1倍后,剩下的1代表割的边数,并且它不会超过m,不会影响最小割值

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <queue>
      
    using namespace std;
      
    typedef long long LL;
      
    void read(int &x) {
        char c;bool flag = 0;
        while((c=getchar())<'0'||c>'9') flag |= (c=='-');
        x=c-'0';while((c=getchar())>='0'&&c<='9') x = (x<<3)+(x<<1)+c-'0';
        flag?x=-x:x;
    }
      
    #define MAXX 6000
    #define N 300
    const int inf = ~0u>>2;
      
    struct E {
        int to,flow,next;
        E(int to=0,int flow=0,int next=0):to(to),flow(flow),next(next){}
    }g[MAXX];
    int tot = 1,fr[N];
      
    void Add(int from,int to,int flow) {
    //cout<<"E:"<<from<<" "<<to<<" "<<flow<<"\n";
        g[++tot] = E(to,flow,fr[from]);
        fr[from] = tot;
        g[++tot] = E(from,0,fr[to]);
        fr[to] = tot;
    }
      
    int n,k,m;
    int d[N],st,ed;
      
    bool bfs() {
        memset(d,-1,sizeof d);
        queue<int> q;
        q.push(st); d[st] = 0;
        while(q.size()) {
            int t = q.front(); q.pop();
            for (int i = fr[t]; i; i = g[i].next) {
                int to = g[i].to;
                if(d[to] == -1 && g[i].flow) {
                    d[to] = d[t]+1;
                    q.push(to);
                }
            }
        }
        return d[ed] != -1;
    }
      
    int dfs(int t,int mf) {
        if(t == ed || mf == 0) return mf;
        int tmp = 0;
        for (int i = fr[t]; i; i = g[i].next) {
            if(mf == 0 || g[i].flow == 0 || d[g[i].to] != d[t]+1) continue;
            int f = dfs(g[i].to,min(mf,g[i].flow));
            mf -= f; tmp += f;
            g[i].flow -= f; g[i^1].flow += f;if(mf==tmp) return mf;
        }
        if(mf) d[t] = -1;
        return tmp;
    }
      
    int Dinic(int s,int t) {
        st = s; ed = t;int max_flow = 0;
        while(bfs()) max_flow += dfs(st,inf);
        return max_flow;
    }
      
      
    int main() {
	   int T,s,t; cin >> T;
	   while (T--) {
	  	  cin >> n >> m >> s >> t;
		  tot = 1;
		  for (int i = 0; i <= n+1; i++) fr[i] = 0;
		  for (int i = 1; i <= m; i++) {
			int u,v,w;
			cin >> u >> v >> w;
			Add(u,v,w*(m+1)+1);
	//		Add(v,u,0); 
		  }
		  printf("%d\n",Dinic(s,t)%(m+1));
	   }
	   return 0; 
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值