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

Posted Lsxxxxxxxxxxxxx

tags:

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6214

题意:求边数最小的割。

解法:

建边的时候每条边权 w = w * (E + 1) + 1;
这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1)

道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等
但边权变换后只有边数小的才是最小割了

 乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果

因为假设最小割=k,那么现在新图的最小割为k*(E+1)+p,p为割的边数,本质上是,原来你割一条边,需要代价,

由于你要求边数最小 所以你多割一条边,就多一的代价,但是这个代价不足以影响到原来的代价。
原来割一条边,代价xi,现在割一条边,代价xi*A+1,只要让A>m+1,m为边数,即使割了所有的边,自己加上去的代价也就m
 
在QQ群里还看到一种解法,就是跑2次Dinic,这个显然是不对的吧。。最小割一定是满流,但是漫流的不一定是最小割吧。。。
 
#include <bits/stdc++.h>
using namespace std;
const int maxn = 410;
const int maxm = 50010;
const int inf = 0x3f3f3f3f;
struct G
{
    int v, cap, next;
    G() {}
    G(int v, int cap, int next) : v(v), cap(cap), next(next) {}
} E[maxm];
int p[maxn], T;
int d[maxn], temp_p[maxn], qw[maxn]; //d顶点到源点的距离标号,temp_p当前狐优化,qw队列
void init()
{
    memset(p, -1, sizeof(p));
    T = 0;
}
void add(int u, int v, int cap)
{
    E[T] = G(v, cap, p[u]);
    p[u] = T++;
    E[T] = G(u, 0, p[v]);
    p[v] = T++;
}
bool bfs(int st, int en, int n)
{
    int i, u, v, head, tail;
    for(i = 0; i <= n; i++) d[i] = -1;
    head = tail = 0;
    d[st] = 0;
    qw[tail] = st;
    while(head <= tail)
    {
        u = qw[head++];
        for(i = p[u]; i + 1; i = E[i].next)
        {
            v = E[i].v;
            if(d[v] == -1 && E[i].cap > 0)
            {
                d[v] = d[u] + 1;
                qw[++tail] = v;
            }
        }
    }
    return (d[en] != -1);
}
int dfs(int u, int en, int f)
{
    if(u == en || f == 0) return f;
    int flow = 0, temp;
    for(; temp_p[u] + 1; temp_p[u] = E[temp_p[u]].next)
    {
        G& e = E[temp_p[u]];
        if(d[u] + 1 == d[e.v])
        {
            temp = dfs(e.v, en, min(f, e.cap));
            if(temp > 0)
            {
                e.cap -= temp;
                E[temp_p[u] ^ 1].cap += temp;
                flow += temp;
                f -= temp;
                if(f == 0)  break;
            }
        }
    }
    return flow;
}
int dinic(int st, int en, int n)
{
    int i, ans = 0;
    while(bfs(st, en, n))
    {
        for(i = 0; i <= n; i++) temp_p[i] = p[i];
        ans += dfs(st, en, inf);
    }
    return ans;
}

int main()
{
    int T, n, m;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &n,&m);
        init();
        int s, t;
        scanf("%d %d", &s, &t);
        for(int i=1; i<=m; i++){
            int u, v, w;
            scanf("%d %d %d", &u,&v,&w);
            add(u, v, w*(m+1)+1);
        }
        int ans = dinic(s, t, n+1);
        printf("%d\n", ans%(m+1));
    }
    return 0;
}

 

以上是关于HDU 6214 Smallest Minimum Cut 最小割,权值编码的主要内容,如果未能解决你的问题,请参考以下文章

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

HDU 6214 最小割边

hdu 6214

HDU 6214最少的最小割边数

2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数

Leetcode 1509. Minimum Difference Between Largest and Smallest Value in Three Moves