zoukankan      html  css  js  c++  java
  • CF546E Soldier and Traveling(网络流,最大流)

    CF546E Soldier and Traveling

    题目描述

    In the country there are (n) cities and (m) bidirectional roads between them. Each city has an army. Army of the i-th city consists of (a_{i}) soldiers. Now soldiers roam. After roaming each soldier has to either stay in his city or to go to the one of neighboring cities by at moving along at most one road.

    Check if is it possible that after roaming there will be exactly (b_{i}) soldiers in the i-th city.

    输入输出格式

    输入格式:

    First line of input consists of two integers n n n and m m m ( (1<=n<=100) , (0<=m<=200) ).

    Next line contains (n) integers (a_{1},a_{2},...,a_{n}) ( (0<=a_{i}<=100) ).

    Next line contains (n) integers (b_{1},b_{2},...,b_{n})​ ( (0<=b_{i}<=100) ).

    Then m lines follow, each of them consists of two integers p and q ( (1<=p,q<=n , p≠q) ) denoting that there is an undirected road between cities p and q .

    It is guaranteed that there is at most one road between each pair of cities.

    输出格式:

    If the conditions can not be met output single word "NO".

    Otherwise output word "YES" and then n n n lines, each of them consisting of n integers. Number in the i-th line in the j-th column should denote how many soldiers should road from city i to city j(if i≠j ) or how many soldiers should stay in city i (if i=j ).

    If there are several possible answers you may output any of them.

    输入输出样例

    输入样例#1: 复制

    4 4
    1 2 6 3
    3 5 3 1
    1 2
    2 3
    3 4
    4 2

    输出样例#1: 复制

    YES
    1 0 0 0
    2 0 0 0
    0 5 1 0
    0 0 2 1

    输入样例#2: 复制

    2 0
    1 2
    2 1

    输出样例#2: 复制

    NO



    题解


    题意大概就是给你 (n) 个城市,(m) 条边。
    然后人只能从走相邻边相连的城市。
    现在给你初始城市的每一个人数,再给一组每个城市人数。询问是否可以从当前人数变换到给定人数。如果能,输入“YES”并输出方案,不能则输出“NO”。

    网络流就是建图嘛。。。
    建好图一般就没有什么难度了qwq(dalao雾怼)
    那么怎么建呢?
    我们设一个源点和汇点。
    然后把一个城市拆成两个点。
    入点 (i) 限度设为 (a_i) ,出点 (i+n) 限度设为 (b_{i})
    这样就只要判断汇点的最大流是否与 (b_i) 相等了。
    Ps: 原本的人数和后来方案的人数应该相等,且一定要先判定。

    怎么输出方案?
    看反悔路径的流量就好了。
    有就标记一下并输出。



    代码


    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int N=1001;
    struct node{
        int c,to,next;
    }e[N<<1];
    int num=1,head[N<<3],flag;
    int dep[N<<3],n,m,a[N<<3],b[N<<3],sum,tot,s,t;
    int map[N][N];
    int read(){
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void add(int from,int to,int c){
        num++;
        e[num].to=to;
        e[num].c=c;
        e[num].next=head[from];
        head[from]=num;
    }
    
    bool bfs(){
        memset(dep,0,sizeof(dep));
        queue<int>q;q.push(s);dep[s]=1;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(!dep[v]&&e[i].c){
                    dep[v]=dep[u]+1;q.push(v);
                }
            }
        }
        return dep[t];
    }
    
    int dfs(int x,int cap){
        if(x==t)return cap;
        int addx=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(dep[v]==dep[x]+1&&e[i].c){
                int tmp=dfs(v,min(cap-addx,e[i].c));
                e[i].c-=tmp;e[i^1].c+=tmp;addx+=tmp;
            }
        }
        return addx;
    }
    
    int dinic(){
        int ans=0;
        while(bfs())ans+=dfs(s,10000000);
        return ans;
    }
    
    int main()
    {
        n=read();m=read();s=0,t=n+n+1;
        for(int i=1;i<=n;i++)a[i]=read(),add(s,i,a[i]),add(i,s,0),tot+=a[i];
        for(int i=1;i<=n;i++)b[i]=read(),sum+=b[i],add(i+n,t,b[i]),add(t,i+n,0);
        for(int i=1;i<=n;i++)add(i,i+n,99999999),add(i+n,i,0);
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
        //	if(x<y)swap(x,y);
            add(x,y+n,99999999);add(y+n,x,0);
            add(y,x+n,99999999);add(x+n,y,0);
        }
        //cout<<sum<<' '<<dinic();
        if(tot!=sum){printf("NO");return 0;}
        int ans=dinic();
        if(sum==ans){printf("YES
    ");
            for(int i=1;i<=n;i++){
                for(int j=head[i];j;j=e[j].next){
                    int v=e[j].to;
                    if(v>n)
                    map[i][v-n]=e[j^1].c;
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++)
                cout<<map[i][j]<<' ';
                cout<<endl;
            }
        }
        else printf("NO");
        return 0;
    }
    
  • 相关阅读:
    评论啦 测试 PHP
    简易JSON格式化 PHP
    36进制 PHP
    CSS3字体阴影演示 PHP
    IE下获取所有客户端字体,设置背景色 PHP
    获取页面宽高数据 PHP
    recognize和recognition
    增强Activex控件,暴露method方法,在javascript中操作activex控件并调用web service方法
    javascript 也可以用try catch了.
    toggle
  • 原文地址:https://www.cnblogs.com/hhh1109/p/9362553.html
Copyright © 2011-2022 走看看