zoukankan      html  css  js  c++  java
  • CF546E Soldier and Traveling

    题目描述

    In the country there are n n n cities and m m m bidirectional roads between them. Each city has an army. Army of the i i i -th city consists of ai a_{i} ai 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 bi b_{i} bi soldiers in the i i i -th city.

    输入输出格式

    输入格式:

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

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

    Next line contains n n n integers b1,b2,...,bn b_{1},b_{2},...,b_{n} b1,b2,...,bn ( 0<=bi<=100 0<=b_{i}<=100 0<=bi<=100 ).

    Then m m m lines follow, each of them consists of two integers p p p and q q q ( 1<=p,q<=n 1<=p,q<=n 1<=p,q<=n , p≠q p≠q pq ) denoting that there is an undirected road between cities p p p and q q 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 n n integers. Number in the i i i -th line in the j j j -th column should denote how many soldiers should road from city i i i to city j j j (if i≠j i≠j ij ) or how many soldiers should stay in city i i i (if i=j i=j 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

    Solution:

      本题最大流,建图贼有意思。

      题意就是给定一些点上的初始士兵数,问能否通过相邻间的互相移动(只能邻边之间移动一次),达到每个点的目标士兵数。

      首先我们可以特判出一个非法情况:$sumlimits_{i=1}^{ileq n}{a_i} eqsumlimits_{i=1}^{ileq n}{b_i}$直接无解。

      然后网络流的建图比较常规,源点$s ightarrow i$边权为$a_i$,$i ightarrow j$($i==j$或者$i$与$j$相邻)边权为$inf$,$j ightarrow t$边权为$b_j$。跑出最大流后,判断总流量是否等于$a$的和,输出方案只要扫下中间连的反向边就好了。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    #define debug printf("%d %s
    ",__LINE__,__FUNCTION__)
    using namespace std;
    const int N=505,M=200005,inf=233333333;
    int n,m,s,t=250,a[N],b[N],to[M],net[M],w[M],cnt=1,h[N],dis[N];
    int mp[N][N];
    bool f;
    
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
        return f?-a:a;
    }
    
    il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],w[cnt]=c,h[u]=cnt;}
    
    il bool bfs(){
        queue<int>q;
        memset(dis,-1,sizeof(dis));
        q.push(s),dis[s]=0;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=h[u];i;i=net[i])
                if(dis[to[i]]==-1&&w[i])dis[to[i]]=dis[u]+1,q.push(to[i]);
        }
        return dis[t]!=-1;
    }
    
    il int dfs(int u,int op){
        if(u==t)return op;
        int flow=0,used=0;
        for(int i=h[u];i;i=net[i]){
            int v=to[i];
            if(dis[v]==dis[u]+1&&w[i]>0){
                used=dfs(v,min(w[i],op));
                if(!used)continue;
                flow+=used,op-=used;
                w[i]-=used,w[i^1]+=used;
                if(!op)break;
            }
        }
        if(!flow)dis[u]=-1;
        return flow;
    }
    
    il void init(){
        n=gi(),m=gi();
        For(i,1,n) a[i]=gi(),add(s,i,a[i]),add(i,s,0); For(i,1,n) b[i]=gi(),add(i+n,t,b[i]),add(t,i+n,0);
        int u,v,c;
        For(i,1,m) u=gi(),v=gi(),add(u,v+n,inf),add(v+n,u,0),add(v,u+n,inf),add(u+n,v,0);
        For(i,1,n) add(i,i+n,inf),add(i+n,i,0);
    }
    
    il void solve(){
        init();
        int ans=0,ta=0,tb=0;
        For(i,1,n) ta+=a[i],tb+=b[i];
        if(ta!=tb) puts("NO");
        else {
            while(bfs())ans+=dfs(s,inf);
            if(ans!=ta)puts("NO");
            else {
                puts("YES");
                For(u,1,n) {
                    for(int i=h[u+n];i;i=net[i])
                        if(w[i]!=inf&&to[i]!=t) mp[to[i]][u]=w[i];
                }
                For(i,1,n) {For(j,1,n) printf("%d ",mp[i][j]); printf("
    ");}
            }
        }
    }
    
    int main(){
        solve();
        return 0;
    }
  • 相关阅读:
    [JavaScript] 数组去重
    [JavaScript] console.log只在查看时才会读取这个打印的对象,并把此刻相关属性和值显示出来
    [Vuejs] 点击单选框触发两次点击事件的处理
    [Vuejs] 给ref赋值需要注意的问题
    [Vuejs] Vue解决代理设置导致浏览器Session丢失的问题
    [Vuejs] 在vue各个组件中应用全局scss变量
    [JavaScript] 跳出循环方法总结
    [JavaScript] 根据指定宽度截取字符串
    [Element-UI] 使用Element-UI的DateTimePicker组件报错:Cannot read property 'getHours' of undefined
    [Vuejs] 组件 v-if 和 v-show 切换时生命周期钩子的执行
  • 原文地址:https://www.cnblogs.com/five20/p/9356571.html
Copyright © 2011-2022 走看看