• 「日常训练」 Soldier and Traveling (CFR304D2E)


    题意 (CodeForces 546E)

    对一个无向图,给出图的情况与各个节点的人数/目标人数。每个节点的人只可以待在自己的城市或走到与他相邻的节点。
    问最后是否有解,输出一可行解(我以为是必须和答案一样,然后本机调了半天死活不一样,交上去结果A了- -)。

    分析

    典型的网络流。问题在于建模。如何解决两个节点的人数->目标人数?
    考虑到我们始终要和这两个状态打交道,不妨将每个结点拆成两个(转移前&转移后),这两个点间的流量是INF。如果两点相连(不妨设为u,u',v,v'),那么uuvv′vvuu′分别有流量为INF的边。
    转移前的点连接一个源点,其间的边流量为它们的人数,转移后的点连接一个汇点,边流量同理。
    建模完后跑一遍最大流就有结果了,如果汇点没有那么多人那么无解,反之有解。
    接下来的问题是如何求移动的人数。还记得增广路怎么求的吗?(紫书p367)其中,反向边的流量就是移动的具体数目。这样,我们就能够得出具体的移动方法了。
    第一次写网络流,以后还要多加努力。

    代码

    #include <bits/stdc++.h>
    #define MP make_pair
    #define PB push_back
    #define fi first
    #define se second
    #define ZERO(x) memset((x), 0, sizeof(x))
    #define ALL(x) (x).begin(),(x).end()
    #define rep(i, a, b) for (int i = (a); i <= (b); ++i)
    #define per(i, a, b) for (int i = (a); i >= (b); --i)
    #define QUICKIO                  
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    using namespace std;
    using ll = long long;
    using ull = unsigned long long;
    using pi = pair<int,int>;
    // 做题解
    
    const int MAXN=1005;  
    //const int MAXM=3005;  
    const int INF=0x3f3f3f3f;  
    struct Edge  
    {  
        int from,to,cap,flow;
        Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl) {}
    };
    
    struct Dinic
    {
        int n,m,s,t;
        vector<Edge> edges;
        vector<int> G[MAXN];
        void AddEdge(int _f,int _t,int _c)
        {
            edges.PB(Edge(_f,_t,_c,0));
            edges.PB(Edge(_t,_f,0,0));
            m=edges.size();
            G[_f].PB(m-2);
            G[_t].PB(m-1);
        }
        bool vis[MAXN];
        int d[MAXN],cur[MAXN];
    
        bool BFS()
        {
            ZERO(vis);
            queue<int> q;
            q.push(s);
            d[s]=0;
            vis[s]=true;
            while(!q.empty())
            {
                int x=q.front(); q.pop();
                rep(i,0,G[x].size()-1)
                {
                    Edge& e=edges[G[x][i]];
                    if(!vis[e.to] && e.cap>e.flow)
                    {
                        vis[e.to]=true;
                        d[e.to]=d[x]+1;
                        q.push(e.to);
                    }
                }
            }
            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].size();++i)
            {
                Edge& e=edges[G[x][i]];
                if(d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0)
                {
                    e.flow+=f;
                    edges[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())
            {
                ZERO(cur);
                flow+=DFS(s,INF);
            }
            return flow;
        }
    };
    
    int main()
    {
        Dinic dinic;
        int n,m;
        cin>>n>>m;
        dinic.n=2*n+2;
        //dinic.s=0; dinic.t=n+1;
        ll ta=0,tb=0;
        rep(i,1,n)
        {
            int tmp; cin>>tmp;
            dinic.AddEdge(0,i,tmp);
            ta+=tmp;
        }
        rep(i,1,n)
        {
            int tmp; cin>>tmp;
            dinic.AddEdge(i+n,2*n+1,tmp);
            tb+=tmp;
        }
        rep(i,1,n)
            dinic.AddEdge(i,i+n,INF);
        rep(i,1,m)
        {
            int a,b; cin>>a>>b;
            dinic.AddEdge(a,b+n,INF);
            dinic.AddEdge(b,a+n,INF);
        }
        int mf=dinic.MaxFlow(0,2*n+1);
        if(mf==ta && mf==tb)
        {
            cout<<"YES"<<endl;
            int f[105][105];
            ZERO(f);
            for(int i=0;i<dinic.m;i+=2)
            {
                int v=dinic.edges[i].to,u=dinic.edges[i^1].to;
                //cout<<u<<" "<<v-n<<" "<<dinic.edges[i].flow<<endl;
                if(u>=1 && u<=n)
                {
                    f[u][v-n]=dinic.edges[i].flow;
                }
    
            }
            rep(i,1,n)
            {
                rep(j,1,n)
                {
                    cout<<string(j==1 ? "" : " ")<<f[i][j]; 
                }
                cout<<endl;
            }
        }
        else cout<<"NO"<<endl;
        return 0;
    }
    如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
  • 相关阅读:
    lightoj-1047
    lightoj-1044
    lightoj-1045
    lightoj-1082
    LeetCode偶尔一题 —— 19. 删除链表的倒数第N个节点
    Python 3.52官方文档翻译 http://usyiyi.cn/translate/python_352/library/index.html 必看!
    Python3 time模块
    JavaScript CSS 等前端推荐
    Python之 七级字典查询
    将Sublime Text 3设置为Python全栈开发环境(转一个链接)
  • 原文地址:https://www.cnblogs.com/samhx/p/Codeforces-546E.html
Copyright © 2020-2023  润新知