HDU 6214 Smallest Minimum Cut 2017青岛网赛1009(最小割最小割边)

15 篇文章 0 订阅


Smallest Minimum Cut

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


Problem Description
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.
 

Input
The input contains several test cases and the first line is the total number of cases  T (1T300) .
Each case describes a network  G , and the first line contains two integers  n (2n200)  and  m (0m1000)  indicating the sizes of nodes and edges. All nodes in the network are labelled from  1  to  n .
The second line contains two different integers  s  and  t (1s,tn)  corresponding to the source and sink.
Each of the next  m  lines contains three integers  u,v  and  w (1w255)  describing a directed edge from node  u  to  v  with capacity  w .
 

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
 

Source
  
  
输入输出测试
 

Statistic |  Submit |  Clarifications |  Back

建边的时候每条边权 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

至于跑两次Dinic(), 是不对的, 其实很简单, 最小割一定是满流, 但是满流的不一定是最小割。。。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
const int INF = 1e9;
const int maxn = 1e3 + 7;
const int maxv = 2e4 + 5;
int head[maxv], cur[maxv], d[maxv], s, t, k, k1, sum, book[maxn];
int n, m;
void init()
{
    k = 0;
    memset(head, -1, sizeof(head));
}
struct node
{
    int v, w, next;
}edge[maxv];
void addEdge(int u, int v, int w)
{
    edge[k].v = v;
    edge[k].w = w;
    edge[k].next = head[u];
    head[u] = k++;
    edge[k].v = u;
    edge[k].w = 0;
    edge[k].next = head[v];
    head[v] = k++;

}
int Q[maxv];
int bfs()
{
    memset(d, 0, sizeof(d));
    d[s] = 1;
    int frnt = 0, rear = 0;
    Q[rear++] = s;
    while(frnt != rear)
    {
        int u = Q[frnt++];
        if(u == t) return 1;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int to = edge[i].v, w = edge[i].w;
            if(w && d[to] == 0)
            {
                d[to] = d[u] + 1;
                if(to == t) return 1;
                Q[rear++] = to;
            }
        }
    }
    return 0;
}
int dfs(int u, int maxflow)
{
    if(u == t || !maxflow) return maxflow;
    int ret = 0;
    for(int& i = cur[u]; i != -1; i = edge[i].next)
    {
        int to = edge[i].v, w = edge[i].w;
        if(w && d[to] == d[u]+1)
        {
            int f = dfs(to, min(maxflow-ret, w));
            edge[i].w -= f;
            edge[i^1].w += f;
            ret += f;
            if(ret == maxflow) return ret;
        }
    }
    return ret;
}
int Dinic()
{
    int ans = 0;
    while(bfs() == 1)
    {
        memcpy(cur, head, sizeof(head));
        ans += dfs(s, INF);
    }
    return ans;
}
int main()
{
    int _;
    scanf("%d", &_);
    while(_--)
    {
        int x, y, z;
        init();
        scanf("%d%d", &n, &m);
        scanf("%d%d", &s, &t);
        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &x, &y, &z);
            addEdge(x, y, z*(m+1)+1);
        }
//        Dinic();
//        for(int i = 0;i < k; i += 2)
//        {
//            if(edge[i].w == 0)
//            {
//                edge[i].w = 1;
//                edge[i^1].w = 0;
//            }
//            else
//            {
//                edge[i].w = INF;
//                edge[i^1].w = 0;
//            }
//        }
        printf("%d\n", Dinic()%(m+1));
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值