UVA10480:Sabotage(最小割+输出)

Sabotage

题目链接:https://vjudge.net/problem/UVA-10480

Description:

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:

扫描二维码关注公众号,回复: 4520361 查看本文章

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

题意:

给出起点1和终点2,并且给出一些边的边权,现在要截断一些边使1和2彻底隔离。问怎样截断花费最小。

题解:

就是一个最小割,起点1在S集,终点2在T集。

最后输出的时候注意一下就好了,从起点1出发,如果遇到容量为0的边那么这条边就是一条割了。注意并不是所有容量为0的边都是割。

这里我有个问题,为什么在最后dfs的时候输出结果不行,记录一下再输出就可以A...希望大佬不吝赐教。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#define INF 100000000
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 55 ,M = 505 ;
int head[N],d[N];
const int s = 1,t = 2;
int tot ;
struct Edge{
    int u,v,next,c;
}e[M<<1];
void adde(int u,int v,int c){
    e[tot].u=u;e[tot].v=v;e[tot].c=c;e[tot].next=head[u];head[u]=tot++;
    e[tot].u=v;e[tot].v=u;e[tot].c=c;e[tot].next=head[v];head[v]=tot++;
}
int n,m;
int bfs(){
    memset(d,0,sizeof(d));d[1]=1;
    queue <int > q;q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(e[i].c>0 && !d[v]){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    return d[t]!=0;
}
ll dfs(int u,int a){
    if(u==t || a==0) return a;
    ll flow = 0,f;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(d[v]!=d[u]+1) continue ;
        f=dfs(v,min(e[i].c,a));
        if(f>0){
            e[i].c-=f;
            e[i^1].c+=f;
            flow+=f;
            a-=f;
            if(a==0) break ;
        }
    }
    if(!flow) d[u]=-1;
    return flow ;
}
void Dinic(){
    ll tmp=0;
    while(bfs()) tmp+=dfs(1,INF);
    return ;
}
int vis[N];
void Go(int u){
    vis[u]=1;
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(vis[v]) continue ;
        if(e[i].c>0) Go(v);
        if(e[i].c==0) printf("%d %d\n",u,v);  //这样输出不行 
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        if(!n && !m) break ;
        tot=0;memset(head,-1,sizeof(head));
        int cnt = 0;
        for(int i=1;i<=m;i++){
            int u,v,c;
            scanf("%d%d%d",&u,&v,&c);
            adde(u,v,c);
        }
        Dinic();
        memset(vis,0,sizeof(vis));
        Go(1);
        /*for(int i=0;i<tot;i+=2){ //
            int u=e[i].u,v=e[i].v;
            if((vis[u]&&!vis[v]) || (!vis[u]&&vis[v])) printf("%d %d\n",u,v);
        }*/
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/10124734.html