HDU 6214 最小割边

Posted 树的种子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6214 最小割边相关的知识,希望对你有一定的参考价值。

双倍经验题:HDU 6214,3987

求最小割的最小边。

 

方案一:

首先跑最大流,这个时候割上都满载了,于是将满载的边 cap = 1,其他 inf ,再跑最大流,这个时候限定这个网络的关键边就是那个最少边的那个割。

 

方案二:

奇技淫巧,将每条边 cap* A + 1,最大流 = flow / A ,最小割边 = fow % A;

原理:每条边容量扩大 到 cap * A + 1,那么最大流也一定扩大到 *A + 1,原图是多解,但是新图,

例如最少边的个是2条边,那么他就扩大到了 *A + 2,其他的就更大,那么就变成唯一解了。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1005;
const long long INF = 0x3f3f3f3f3f3f3f3f;

struct Edge
{
    int from,to;
    long long cap,flow;
};

struct Dinic
{
    int n,m,s,t;
    vector<Edge> edge;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

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

    void AddEdge (int from,int to,long long cap)
    {
        edge.push_back((Edge){from,to,cap,0});
        edge.push_back((Edge){to,from,0,0});
        m = edge.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 = edge[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];
    }

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

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

int main()
{
    int T;
    scanf("%d",&T);

    for(int z = 1; z <= T; z++) {
        int n,m;
        scanf("%d%d",&n,&m);
        int s,t;
        scanf("%d%d",&s,&t);
        s--;
        t--;
        sol.init();
        for(int i = 0; i < m; i++) {
            int u,v;

            long long c;
            scanf("%d%d%I64d",&u,&v,&c);
            u--;
            v--;
            sol.AddEdge(u,v,c*200001+1);
        }

        printf("%lld\n",sol.Maxflow(s,t)%200001);
    }

    return 0;
}

 

以上是关于HDU 6214 最小割边的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6214 Smallest Minimum Cut 最小割,权值编码

hdu 6214

hdu 3204(最小割--关键割边)

[HDU4738]Caocao's Bridges(求割边最小权值)

hdu 6214 Smallest Minimum Cut[最大流]

hdu-4738(tarjan割边)