zoukankan      html  css  js  c++  java
  • Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流

    题目链接:

    http://codeforces.com/problemset/problem/546/E

    E. Soldier and Traveling

    time limit per test1 second
    memory limit per test256 megabytes
    #### 问题描述 > 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 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 soldiers in the i-th city. #### 输入 > First line of input consists of two integers n and m (1 ≤ n ≤ 100, 0 ≤ m ≤ 200). > > Next line contains n integers a1, a2, ..., an (0 ≤ ai ≤ 100). > > Next line contains n integers b1, b2, ..., bn (0 ≤ bi ≤ 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 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. ####样例输入 > 4 4 > 1 2 6 3 > 3 5 3 1 > 1 2 > 2 3 > 3 4 > 4 2

    样例输出

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

    题意

    给你n个点,m条边的图,每个点有a[i]个士兵,现在要重新部署士兵,每个士兵最多只能移动到相邻的点,问是否能移动成每个点有b[i]个士兵。

    题解

    最大流,把每个点拆成两个点,v,v',v与源点连容量为a[v],v'与汇点连容量为b[v],对于边(u,v),拆成(u,v'),(v,u')然后跑最大流。

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef __int64 LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-8;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=222;
    
    struct Edge{
        int u,v,cap,flow;
        Edge(int u,int v,int c,int f):u(u),v(v),cap(c),flow(f){}
    };
    
    struct Dinic{
        int n,m,s,t;
        vector<Edge> egs;
        VI G[maxn];
        bool vis[maxn];
        int d[maxn];
        int cur[maxn];
    
        void init(int n){
            this->n=n;
            for(int i=0;i<n;i++) G[i].clear();
            egs.clear();
        }
    
        void addEdge(int u,int v,int cap){
            egs.pb(Edge(u,v,cap,0));
            egs.pb(Edge(v,u,0,0));
            m=egs.sz();
            G[u].pb(m-2);
            G[v].pb(m-1);
        }
    
        bool BFS(){
            clr(vis,0);
            queue<int> Q;
            d[s]=0,Q.push(s),vis[s]=1;
            while(!Q.empty()){
                int x=Q.front(); Q.pop();
                rep(i,0,G[x].sz()){
                    Edge& e=egs[G[x][i]];
                    if(!vis[e.v]&&e.cap>e.flow){
                        vis[e.v]=1;
                        d[e.v]=d[x]+1;
                        Q.push(e.v);
                    }
                }
            }
            return vis[t];
        }
    
        int DFS(int x,int a){
            if(x==t||a==0) return a;
            int flow=0,f;
            for(int &i=cur[x];i<G[x].sz();i++){
                Edge& e=egs[G[x][i]];
                if(d[x]+1==d[e.v]&&(f=DFS(e.v,min(a,e.cap-e.flow)))>0){
                    e.flow+=f;
                    egs[G[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0) break;
                }
            }
            return flow;
        }
    
        int maxflow(int s,int t){
            this->s=s;
            this->t=t;
            int flow=0;
            while(BFS()){
                clr(cur,0);
                flow+=DFS(s,INF);
            }
            return flow;
        }
        int mat[maxn][maxn];
        void print(int n){
            clr(mat,0);
            for(int i=0;i<m;i+=2){
                Edge& e=egs[i];
                if(e.flow>0&&e.cap==INF){
                    mat[e.u][e.v-n]+=e.flow;
                }
            }
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    prf("%d",mat[i][j]);
                    if(j==n) prf("
    ");
                    else prf(" ");
                }
            }
        }
    }din;
    
    int n,m;
    int a[maxn],b[maxn];
    
    int main() {
        scf("%d%d",&n,&m);
        int suma=0,sumb=0;
        for(int i=1;i<=n;i++){
            scf("%d",&a[i]);
            suma+=a[i];
        }
        for(int i=1;i<=n;i++){
            scf("%d",&b[i]);
            sumb+=b[i];
        }
    
        if(suma!=sumb){
            prf("NO
    "); return 0;
        }
    
        din.init(n*2+2);
    
        for(int i=1;i<=n;i++){
            din.addEdge(0,i,a[i]);
            din.addEdge(i+n,2*n+1,b[i]);
            ///这条边保证士兵能留在原来的城市
            din.addEdge(i,i+n,INF);
        }
    
        rep(i,0,m){
            int u,v;
            scf("%d%d",&u,&v);
            din.addEdge(u,v+n,INF);
            din.addEdge(v,u+n,INF);
        }
    
        int ans=din.maxflow(0,2*n+1);
    //    bug(ans);
    
        if(ans!=suma){
            prf("NO
    "); return 0;
        }
        prf("YES
    ");
        din.print(n);
    
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    Notes

    这题一个关键的拆点没考虑到orz,,老是想着吧a[i]-b[i],但这思路好像是有问题的!,

  • 相关阅读:
    虚拟机安装RHEL8.0.0
    给KVM添加新的磁盘
    RedHat7.4安装在个人电脑(笔记本)中安装遇到的问题总结
    shell编程-ssh免交互批量分发公钥脚本
    Error:Connection activation failed: No suitable device found for this connection 问题最新解决方案
    Linux下系统防火墙的发展历程和怎样学好防火墙(iptalbes和firewalld)
    Linux bash命令行常用快捷键(Xshell和secure CRT以及gnome-terminal)
    编写mysql多实例启动脚本
    RHEL7配置端口转发和地址伪装
    java中的事务,四大特性,并发造成的问题,隔离级别
  • 原文地址:https://www.cnblogs.com/fenice/p/5887320.html
Copyright © 2011-2022 走看看