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 military
super power has decided to invade the country and reinstall the old regime.
For this operation to be successful, communication between the capital and the largest city must
be completely cut. This is a difficult task, since all cities in the country are connected by a computer
network using the Internet Protocol, which allows messages to take any path through the network.
Because of this, the network must be completely split in two parts, with the capital in one part and
the largest city in the other, and with no connections between the parts.
There are large differences in the costs of sabotaging different connections, since some are much
more easy to get to than others.
Write a program that, given a network specification and the costs of sabotaging each connection,
determines which connections to cut in order to separate the capital and the largest city to the lowest
possible cost.
Input:
Input file contains several sets of input. The description of each set is given below.
The first line of each set has two integers, separated by a space: First one the number of cities, n in
the network, which is at most 50. The second one is the total number of connections, m, at most 500.
The following m lines specify the connections. Each line has three parts separated by spaces: The
first two are the cities tied together by that connection (numbers in the range 1 − n). Then follows the
cost of cutting the connection (an integer in the range 1 to 40000000). Each pair of cites can appear at
most once in this list.
Input is terminated by a case where values of n and m are zero. This case should not be processed.
For every input set the capital is city number 1, and the largest city is number 2.

Output:
For each set of input you should produce several lines of output. The description of output for each set
of input is given below:

The output for each set should be the pairs of cities (i.e. numbers) between which the connection
should be cut (in any order), each pair on one line with the numbers separated by a space. If there is
more than one solution, any one of them will do.
Print a blank line after the output for each set of input.

Sample Input:
5 8
1 4 30
1 3 70
5 3 20
4 3 5
4 5 15
5 2 10
3 2 25
2 4 50
5 8
1 4 30
1 3 70
5 3 20
4 3 5
4 5 15
5 2 10
3 2 25
2 4 50
0 0

Sample Output
4 1
3 4
3 5
3 2

4 1
3 4
3 5
3 2

题意:有n个城市和m条路径,每条路径连接着两个城市,路径后是破坏这两个城市联系所需要的花费,现在想要破坏城市1和城市2之间的联系,问最小的花费,输出其要破坏的路径。

即求出最大流,在剩余的残余网络中,原本有路径的点,层数为0的点是汇点部分,而层数不为0的点为源点部分,既然它们之间一开始是有联系的,而现在没有联系,说明它们在求出最大流时被破坏了,输出两点即可。

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int N=1000;

struct node
{
    int v, cost, next;
} no[N];
int layer[N], head[N], k, t;

void Add(int a, int b, int c)
{
    no[k].v = b;
    no[k].cost = c;
    no[k].next = head[a];
    head[a] = k++;

    swap(a, b);

    no[k].v = b;
    no[k].cost = c;
    no[k].next = head[a];
    head[a] = k++;
}

int BFS(int Start, int End)
{
    int i, u, v;
    queue<int>Q;

    memset(layer, 0, sizeof(layer));

    Q.push(Start);
    layer[Start] = 1;

    while (!Q.empty())
    {
        u = Q.front();
        Q.pop();

        if (u == End) return 1;

        for (i = head[u]; i != -1; i = no[i].next)
        {
            v = no[i].v;

            if (no[i].cost && layer[v] == 0)
            {
                layer[v] = layer[u]+1;
                Q.push(v);
            }
        }
    }

    return 0;
}

int DFS(int Start, int End, int mini)
{
    int i, v, ans, cost = 0;

    if (Start == End) return mini;

    for (i = head[Start]; i != -1; i = no[i].next)
    {
        v = no[i].v;

        if (no[i].cost && layer[v] == layer[Start]+1)
        {
            ans = min(no[i].cost, mini-cost);
            ans = DFS(v, End, ans);

            no[i].cost -= ans;
            no[i+1].cost += ans;
            cost += ans;

            if (cost == mini) break;
        }
    }

    if (cost == 0) layer[Start] = 0;

    return cost;
}

void Dinic(int Start, int End)
{
    int t=0;

    while (BFS(Start, End))
        t += DFS(Start, End, INF);
}
int main ()
{
    int n, m, a, b, c, i, A[N], B[N];

    while (scanf("%d%d", &n, &m), n+m)
    {
        memset(head, -1, sizeof(head));
        k = 0;

        for (i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            A[i] = a; B[i] = b;
            Add(a, b, c);
        }

        Dinic(1, 2); ///求出最大流的目的是为了在剩余网络中查找被破坏的路径

        for (i = 1; i <= m; i++)
        {
            if ((!layer[A[i]] && layer[B[i]]) || (layer[A[i]] && !layer[B[i]])) ///层数为0说明求最大流时肯定经过该点,并且它的父节点的层数肯定不为0,只有这样花费才能达到最小,两点之间的路径被破坏
            printf("%d %d\n", A[i], B[i]);
        }
        printf("\n");
    }

    return 0;
}
时间: 2024-12-19 08:57:03

UVa 10480 Sabotage的相关文章

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 (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

J - Sabotage - UVA 10480(最大流)

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

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

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

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f

[UVa] Palindromes(401)

UVA - 401 Palindromes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDED