zoukankan      html  css  js  c++  java
  • UVa10480-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


    题意:求把1和2割开的最小花费,也就是最小割

    #include<map>
    #include<set>
    #include<queue>
    #include<math.h>
    #include<vector>
    #include<string>
    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #define inf 0x3f3f3f3f
    #define ll long long
    #define maxn 100
    #define maxm 2000
    using namespace std;
    struct Edge{
    int to,next;int cap,flow;
    }edge[maxm];
    int tol;
    int head[maxn];
    int gap[maxn],dep[maxn],pre[maxn],cur[maxn];
    void init(){tol=0;memset(head,-1,sizeof(head));memset(edge,0,sizeof(edge));}
    void addedge(int u,int v,int w,int rw){
        edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];edge[tol].flow=0;head[u]=tol++;
        edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];edge[tol].flow=0;head[v]=tol++;
    }
    int sap(int s,int t,int N){
        memset(gap,0,sizeof(gap));memset(dep,0,sizeof(dep));memset(pre,0,sizeof(pre));
        memcpy(cur,head,sizeof(head));
        int u=s;pre[u]=-1;gap[0]=N;int ans=0;
        while(dep[s]<N){
            if(u==t){
                int minn=inf;for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if(minn>edge[i].cap-edge[i].flow)
                    minn=edge[i].cap-edge[i].flow;
                for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]){
                    edge[i].flow+=minn;edge[i^1].flow-=minn;
                }u=s;ans+=minn;continue;
            }
            bool flag=false;int v;
            for(int i=cur[u];i!=-1;i=edge[i].next){
                v=edge[i].to;
                if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u]){
                    flag=true;cur[u]=pre[v]=i;break;
                }
            }if(flag){u=v;continue;}
            int minn=N;
            for(int i=head[u];i!=-1;i=edge[i].next)
            if(edge[i].cap-edge[i].flow && dep[edge[i].to]<minn){
                minn=dep[edge[i].to];cur[u]=i;
                }
            gap[dep[u]]--;if(!gap[dep[u]])return ans;
            dep[u]=minn+1;gap[dep[u]]++;if(u!=s)u=edge[pre[u]^1].to;
            }
            return ans;
    }
    int vis[100];int q[maxn];
    void bfs(int s){
        int front,rear;front=1;rear=1;q[rear]=s;int x,v,i;while(front<=rear){
            x=q[front];front++;for(i=head[x];i!=-1;i=edge[i].next){
                v=edge[i].to;if(vis[v])continue;
                if(edge[i].cap && edge[i].cap>edge[i].flow){
                    rear++;q[rear]=v;vis[v]=1;
                }
            }
        }
    }
    int main(){int n,m,s,t;
        while(~scanf("%d%d",&n,&m)&&(n|m)){
            s=1,t=2;init();
            while(m--){int a,b,c;scanf("%d%d%d",&a,&b,&c);addedge(a,b,c,c);
            }int x=sap(s,t,n);memset(vis,0,sizeof(vis));bfs(s);vis[s]=1;int used[maxn][maxn];memset(used,0,sizeof(used));//cout<<x<<endl;
            for(int i=0;i<tol;i++){int u=edge[i].to,v=edge[i^1].to;
            if(((!vis[u]&&vis[v])||(!vis[v]&&vis[u]))&&used[u][v]==0&&used[v][u]==0){
            used[u][v]=used[v][u]=1;printf("%d %d
    ",u,v);}
            }cout<<endl;
        }
    }




  • 相关阅读:
    现在分词做状语,到,非谓语动词
    成功和失败因素收集
    退拽原理2
    分享到(事件冒泡实例)
    滚动公告(纵向)
    RabbitMQ消息队列(一): Detailed Introduction 详细介绍
    在IDEA中实战Git
    深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例
    MySQL中日期和时间戳互相转换的函数和方法
    【Docker】 windows10 docker 使用
  • 原文地址:https://www.cnblogs.com/da-mei/p/9053264.html
Copyright © 2011-2022 走看看