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;
}
时间: 2024-10-08 11:13:00

HDU 6214 最小割边的相关文章

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

hdu 6214 Smallest Minimum Cut[最大流]

hdu 6214 Smallest Minimum Cut[最大流] 题意:求最小割中最少的边数. 题解:对边权乘个比边大点的数比如300,再加1 ,最后,最大流对300取余就是边数啦.. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<vector> 7 #in

HDU 4160 最小路径覆盖

Dolls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1040    Accepted Submission(s): 496 Problem Description Do you remember the box of Matryoshka dolls last week? Adam just got another box of

HDU 1350 最小路径覆盖

Taxi Cab Scheme Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 707    Accepted Submission(s): 336 Problem Description Running a taxi station is not all that simple. Apart from the obvious dem

String Problem hdu 3374 最小表示法加KMP的next数组

String Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1492    Accepted Submission(s): 662 Problem Description Give you a string with length N, you can generate N strings by left shifts.

hdu 4966 最小树形图

将每门课等级拆成0,1,2,3...a[i]个点,对每个等级大于0的点向它低一级连边,权值为0[意思是,若修了level k,则level(0~k)都当做修了] 将输入的边建边,权值为money[i]. 建立根节点,向每个level 0的点连边,权值为0[因为初始level 0的都修了] 由于题目要求每门课都必须达到最大level,也就是对应图中根节点能到达所有点,问题就变成了求无向图的最小生成树. #include<iostream> #include<cstdio> #incl

HDU 1150 最小点覆盖数

Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5614    Accepted Submission(s): 2804 Problem Description As we all know, machine scheduling is a very classical problem in comput

hdu 2516 最小费用最大流

原来这个代码超时 #include<stdio.h> #include<queue> #include<string.h> using namespace std; #define N 200 #define inf 0x3fffffff int cap[N][N]; int fee[N][N]; int s,t,sum,pre[N]; int spfa() { queue<int>q; int dis[N],visit[N],u,i; memset(pre

HDU 6214【最少的最小割边数】

题目大意如题. 这道题想了很久也没明白题解的做法: 建边的时候每条边权 w = w * (E + 1) + 1; 这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1) 总之先把它当成黑科技背着吧 #include<stdio.h> #include<string.h> #include<queue> using namespace std; struct node { int from; int to; int w; in