Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流 Dinic EK 算法

E. Soldier and Traveling
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

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 aisoldiers. 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.

Input

First line of input consists of two integers n and m (1 ≤ n ≤ 1000 ≤ 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 ≤ np ≠ 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.

Output

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.

Sample test(s)
input
4 4
1 2 6 3
3 5 3 1
1 2
2 3
3 4
4 2
output
YES
1 0 0 0 
2 0 0 0 
0 5 1 0 
0 0 2 1 
input
2 0
1 2
2 1
output
NO
题意,要求,给出一个图,每个点都有个初始的值,要求一种方案能使每个点能达到目标值。每个点的士兵只能走一个城。
网络流,先建立一个模型,把n个点每个点分成入点和出点两个点,连上a[i]的边
如图,建一个s点,连所有入点,建一个e点,连所有的出点。如果i,j连有边,则在出点i与入点j连一条a[i]的边。这样就能保证跑一个最大流之后,如果最大流等于,总人数,就说明,存在解,输出边的流量就是要转移的人。
因为入点的边为a[i],保证了,出的人最多为a[i],因为只能从入点连向出点,所以保证了,士兵只能走一个边。
代码直接使用了模板,有Dinic EK算法的两种实现。
Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流 Dinic EK 算法_第1张图片
#define INF			9000000000
#define EPS			(double)1e-9
#define mod			1000000007
#define PI			3.14159265358979
//*******************************************************************************/
#endif
#define N 405
#define M 100005
#define maxn 450
#define MOD 1000000000000000007
int n,a[N],b[N],s,e,sum,maxf,m,ans[N][N],s1;
struct Edge{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct EdmondsKarp{
    int n,m;
    vector<Edge> edges;//存边 边的两倍
    vector<int> G[maxn];//邻接表,图
    int a[maxn];//起点到i的可改进量
    int p[maxn];//最短路入弧号
    void init(int n){
        FI(n) G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));//反向
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    int Maxflow(int s,int t){
        int flow = 0;
        for(;;){
            memset(a,0,sizeof(a));
            queue<int> Q;
            Q.push(s);
            a[s] = INF;
            while(!Q.empty()){
                int x = Q.front();Q.pop();
                FI(G[x].size()){
                    Edge & e = edges[G[x][i]];
                    if(!a[e.to]&&e.cap > e.flow){
                        p[e.to] = G[x][i];
                        a[e.to] = min(a[x],e.cap - e.flow);
                        Q.push(e.to);
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u = t;u !=s;u = edges[p[u]].from){
                edges[p[u]].flow += a[t];
                edges[p[u] ^ 1].flow -= a[t];
            }
            flow += a[t];
        }
        return flow;
    }
};
struct Dinic{
    int n,m,s,t;
    vector<Edge> edges;//存边 边的两倍
    vector<int> G[maxn];//邻接表,图
    bool vis[maxn];//BFS使用
    int d[maxn];//起点到i的距离
    int cur[maxn];//当前弧下标
    void init(int n){
        FI(n) G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));//反向
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool BFS(){
        memset(vis,0,sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while(!Q.empty()){
            int x = Q.front();Q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge & e  = edges[G[x][i]];
                if(!vis[e.to] && e.cap > e.flow){
                    vis[e.to] = 1;
                    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()){
            memset(cur,0,sizeof(cur));
            flow += DFS(s,INF);
        }
        return flow;
    }
};
//EdmondsKarp Ek;
Dinic Ek;
int main()
{
    while(S2(n,m)!=EOF)
    {
        Ek.init(n + n + 2);sum = 0;
        FI(n){
            S(a[i]);s1+=a[i];
            Ek.AddEdge(n + n,i + i,a[i]);
        }
        FI(n){
            S(b[i]);
            Ek.AddEdge(i + i + 1,n + n + 1,b[i]);
            Ek.AddEdge(i + i,i + i + 1,a[i]);
            sum += b[i];
        }

        FI(m){
            S2(s,e);s--,e--;
            Ek.AddEdge(s + s,e + e + 1,a[s]);
            Ek.AddEdge(e + e,s + s + 1,a[e]);
        }
        if(sum != s1){
            printf("NO\n");
            continue;
        }
        maxf = Ek.Maxflow(n + n,n + n + 1);
        if(sum == maxf){
            printf("YES\n");
            FI(n){
                int s = i + i;
                FJ(Ek.G[s].size()){
                    Edge e = Ek.edges[Ek.G[s][j]];
                    ans[e.from/2][e.to/2] = e.flow;
                    //printf("flow  %d %d %d %d\n",e.from,e.to,e.flow,e.cap);
                }
            }
            FI(n){
                FJ(n){
                    if(j)
                        printf(" %d",ans[i][j]);
                    else
                        printf("%d",ans[i][j]);
                }
                printf("\n");
            }
        }
        else {
            printf("NO\n");
        }
    }
    return 0;
}


你可能感兴趣的:(Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流 Dinic EK 算法)