Sabotage 【UVA - 10480】【最大流割边】

题目链接

很容易会想到是最大流建边,但是同样的这里有坑点,就是有的人去输出边的时候,去把残余网络的流为0的边给输出了,其实不然,我们应当输出的是那些最后跑到深度为0的不能再走下去的点,只要把他们割了,就一定会是最优的解。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 107, maxE = 2e3 + 7, S = 1, T = 2;
int N, M, cnt, head[maxN], cur[maxN];
struct Eddge
{
    int nex, to, flow, old;
    Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c), old(c) {}
}edge[maxE];
inline void addEddge(int u, int v, int flow)
{
    edge[cnt] = Eddge(head[u], v, flow);
    head[u] = cnt++;
}
inline void _add(int u, int v, int flow) { addEddge(u, v, flow); addEddge(v, u, 0); }
int deep[maxN];
queue<int> Q;
inline bool bfs()
{
    memset(deep, 0, sizeof(deep)); deep[S] = 1;
    while(!Q.empty()) Q.pop();
    Q.push(S);
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i=head[u], v, f; ~i; i=edge[i].nex)
        {
            v = edge[i].to; f = edge[i].flow;
            if(f && !deep[v])
            {
                deep[v] = deep[u] + 1;
                Q.push(v);
            }
        }
    }
    return deep[T];
}
inline int dfs(int u, int dist)
{
    if(u == T) return dist;
    for(int &i=cur[u], v, f; ~i; i=edge[i].nex)
    {
        v = edge[i].to; f = edge[i].flow;
        if(f && deep[v] == deep[u] + 1)
        {
            int di = dfs(v, min(dist, f));
            if(di)
            {
                edge[i].flow -= di;
                edge[i^1].flow += di;
                return di;
            }
        }
    }
    return 0;
}
inline void Dinic()
{
    while(bfs())
    {
        for(int i=1; i<=N; i++) cur[i] = head[i];
        while(dfs(S, INF)) ;
    }
}
bool used[55][55];
inline void Out(int u, int fa)
{
    for(int i=head[u], v, f; ~i; i=edge[i].nex)
    {
        v = edge[i].to; f = edge[i].flow;
        if(v == fa) continue;
        if(!deep[v] && edge[i].old)
        {
            if(used[u][v]) continue;
            used[u][v] = used[v][u] = true;
            printf("%d %d\n", u, v);
        }
        else if(edge[i].old > f) { Out(v, u); }
    }
}
inline void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(used, false, sizeof(used));
}
int main()
{
    int Cas = 0;
    while(scanf("%d%d", &N, &M) && (N || M))
    {
        if(Cas++) printf("\n");
        init();
        for(int i=1, u, v, w; i<=M; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            _add(u, v, w);
            _add(v, u, w);
        }
        Dinic();
        Out(S, -1);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/WuliWuliiii/p/10987052.html

时间: 2024-10-10 04:47:59

Sabotage 【UVA - 10480】【最大流割边】的相关文章

J - Sabotage - UVA 10480(最大流)

题目大意:旧政府有一个很庞大的网络系统,可以很方便的指挥他的城市,起义军为了减少伤亡所以决定破坏他们的网络,使他们的首都(1号城市)和最大的城市(2号城市)不能联系,不过破坏不同的网络所花费的代价是不同的,现在起义军想知道最少花费的代价是多少,输出需要破坏的线路. 输入:第一行输入一个N和M,表示城市数和线路数,下面M行,每行有三个整数,表示从破坏城市u到v的线路花费是w. 分析:很明显的最小割问题,我们知道有向图(题目给的是无向图,所以需要建立反边)的最小割等于最大流,所以只需要求出来最大流即

UVA - 10480 Sabotage 最小割,输出割法

UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解:建图直接按给你的图建一下,然后呢跑一下最大流,我们就知道了最小割是多少,答案就是最小割了  . 现在要求输出割法.我们从s开始往前跑,如果某条正向边有流量,我们就按着这条边继续往外走,知道无法再走,把所有经历过的点都染一下色.最后看所有的边,是不是有一头是染色了,另一头没有染色,如果是,这条边就是割

Uva 10480 Sabotage 最大流

表示自从学了网络流,就基本上是一直用dinic 这个题一看就是用最大流,作为常识,两个点之间的最大流等于最小割 但是这个题需要输出割边,然后我就不会了,dinic判流量我觉得也可做,但是一直wa 然后看了看网上的代码,居然用EK暴力,仰慕不已,不过一看数据范围(EK很合理嘛!!!) 关键是用EK可以很容易判断割边 感悟:还是too young too simple 不过让我找回了最初学网络流时的感觉 分析见这里:无限仰慕美女大神 http://blog.csdn.net/ac_lion/arti

UVa 10480 Sabotage

10480  Sabotage:The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebellion.Because of the enormous disturbances this is causing in world economy, an imperialist militarysuper power has decided to invade the

UVA - 10480 Sabotage (Dinic)

The regime of a small but wealthy dictatorship has been abruptly overthrown by an unexpected rebel-lion. Because of the enormous disturbances this is causing in world economy, an imperialist militarysuper power has decided to invade the country and r

【网络流#4】UVA 753 最大流

最近开始刷网络流的题目了,先从紫书上的开始,这道题是P374上的,嘛,总之这道题最终还是参考了一下紫书. 中间是用了STL中map将字符串映射成编号,使用编号总比是用字符串简单的多. 超级源点S与各个设备对应插头类型连一条边,容量为1, 超级汇点T与各个插头连一条边,容量为1 然后如果有转换器,如果x->y,那么从点x连一条容量为正无穷的边到y (因为插头同类型的有无数个) 这样跑一发最大流即可,代码中间套用模板 1 #include<cstdio> 2 #include<cstr

【网络流#5】UVA 11082 最大流

网络流题目最有意思的地方就是构图了,毕竟套模板每个人都会的 现在有一个矩阵,已知前i行元素之和a[i](1<=i<=n),前j列元素之和b[j](1<=j<=m),求一个可行的矩阵,且矩阵每个元素在区间[1,20]内. 这也算是含上下界的网络流了,但是显然,如果将每个元素都减一,就是普通的最大流了,矩阵元素值在区间[0,19]内. 首先求出第i行元素之和r[i],第j列元素之和c[j], 然后就是建图,每行化为一个结点1~n,每列化为一个结点n+1~n+m 源点到1~n,分别连一条

UVa 11082 &amp; 最大流的行列模型

题意: 给出一个矩阵前i行的和与前j列的和,(i∈[1,r],j属于[1,c]),每个元素ai,j∈[1,20],请你还原出这个矩阵,保证有解. SOL: 给网络流建模跪了,神一样的建图,如果我我会怎么做呢?...搜索?然而每个元素具有行,列双重相关性...暴力都打不出来吧... 然而我们顺着搜索的方向想,如果每个点的搜索值最终小于这行的和,那么我们应该做什么?增大它!是不是感觉有点增广的想法出来了------>然而我只是瞎BB...事后觉得可以这么想但考场上并不能这么想出来... 考虑它的建图

Crimewave (Uva 563 最大流拆点)

 Crimewave  Nieuw Knollendam is a very modern town. This becomes clear already whenlooking at the layout of its map, which is just a rectangular grid of streetsand avenues. Being an important trade centre, Nieuw Knollendam also has a lotof banks. Alm