HDU 6214 Smallest Minimum Cut 【最小割】


Smallest Minimum Cut

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit:65535/32768 K (Java/Others)
Total Submission(s): 110    Accepted Submission(s): 33

Problem Description

Consider a network G=(V,E) with source s and sinkt. An s-t cut isa partition of nodes setV intotwo parts such thats andt belong todifferent parts. The cut set is the subset ofE with all edgesconnecting nodes in different parts. A minimum cut is the one whose cut set hasthe minimum summation of capacities. The size of a cut is the number of edgesin 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 ofcasesT (1≤T≤300).
Each case describes a network
G, andthe first line contains two integersn (2≤n≤200) andm (0≤m≤1000) indicating thesizes of nodes and edges. All nodes in the network are labelled from 1 to n.
The second line contains two different integers
s andt (1≤s,tn) correspondingto the source and sink.
Each of the next
m linescontains three integersu,v andw (1≤w≤255) describing adirected edge from nodeu tov with capacityw.

 

 

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


【题意】


给出一个图,求出该图最小割中边数最少的边数是多少。


【思路】


取一个mod,建边的时候每条边权设为w*mod+1,那就跑一下最小割的模板就可以了。这样得到的最大流为maxflow/mod,最小割中的最小边数为maxflow%mod。


那么为什么可以这样做呢?


因为我们边权里的w*mod+1,那个加一就相当于是边数,那么在最小割相同的情况下,边数较小的最小割的maxflow较小。这样就能求出最小割了。


需要注意的是这里的mod应该取得大一些,防止边数增大到一定程度产生“进位”,影响最小割的结果。


#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 205;
const ll mod = 10005;
const int INF = 0x3f3f3f3f;

int n,m;

struct Edge
{
    int from,to;
    ll cap,flow;
    Edge(int u,int v,ll c,ll f):from(u),to(v),cap(c),flow(f) {}
};
struct Dinic
{
    int n,m,s,t;
    vector<Edge>edges;
    vector<int>G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init(int n)
    {
        for (int i=0; i<=n; i++) G[i].clear();
        edges.clear();
    }

    void AddEdge(int from,int to,int cap)
    {
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool BFS()
    {
        memset(vis,0,sizeof(vis));
        queue<int>Q;
        Q.push(s);
        d[s]=0;
        vis[s]=1;
        while (!Q.empty())
        {
            int x=Q.front();
            Q.pop();
            for (int i=0; i<(int)G[x].size(); i++)
            {
                Edge& e=edges[G[x][i]];
                if (!vis[e.to] && e.cap>e.flow)
                {
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    ll DFS(int x,ll a)
    {
        if (x==t || a==0) return a;
        ll flow=0,f;
        for (int& i=cur[x]; i<(int)G[x].size(); i++)
        {
            Edge& e=edges[G[x][i]];
            if (d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if (a==0) break;
            }
        }
        return flow;
    }

    ll Maxflow(int s,int t)
    {
        this->s=s;
        this->t=t;
        ll flow=0;
        while (BFS())
        {
            memset(cur,0,sizeof(cur));
            flow+=DFS(s,INF);
            flow%=mod;
        }
        return flow;
    }
} A;

int main()
{
    int ss,tt;
    int u,v,w;
    rush()
    {
        scanf("%d%d",&n,&m);
        scanf("%d%d",&ss,&tt);
        A.init(n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            A.AddEdge(u,v,(ll)w*mod+1);
        }
        printf("%lld\n",A.Maxflow(ss,tt));
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值