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?≤?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?≤?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算法的两种实现。

#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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-06 09:49:56

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

数学+DP Codeforces Round #304 (Div. 2) D. Soldier and Number Game

题目传送门 1 /* 2 题意:这题就是求b+1到a的因子个数和. 3 数学+DP:a[i]保存i的最小因子,dp[i] = dp[i/a[i]] +1;再来一个前缀和 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-1 14:08:34 8 File Name :B.cpp 9 ******************************

DP+埃氏筛法 Codeforces Round #304 (Div. 2) D. Soldier and Number Game

题目传送门 1 /* 2 题意:b+1,b+2,...,a 所有数的素数个数和 3 DP+埃氏筛法:dp[i] 记录i的素数个数和,若i是素数,则为1:否则它可以从一个数乘以素数递推过来 4 最后改为i之前所有素数个数和,那么ans = dp[a] - dp[b]: 5 详细解释:http://blog.csdn.net/catglory/article/details/45932593 6 */ 7 #include <cstdio> 8 #include <algorithm>

水题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas

题目传送门 1 /* 2 水题:ans = (1+2+3+...+n) * k - n,开long long 3 */ 4 #include <cstdio> 5 #include <algorithm> 6 #include <cstring> 7 #include <cmath> 8 using namespace std; 9 10 typedef long long ll; 11 12 int main(void) //Codeforces Roun

贪心 Codeforces Round #304 (Div. 2) B. Soldier and Badges

题目传送门 1 /* 2 题意:问最少增加多少值使变成递增序列 3 贪心:排序后,每一个值改为前一个值+1,有可能a[i-1] = a[i] + 1,所以要 >= 4 */ 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 using namespace std; 9 10 typedef long long ll; 11 12 const int MAXN = 3e3 + 10;

queue+模拟 Codeforces Round #304 (Div. 2) C. Soldier and Cards

题目传送门 1 /* 2 题意:两堆牌,每次拿出上面的牌做比较,大的一方收走两张牌,直到一方没有牌 3 queue容器:模拟上述过程,当次数达到最大值时判断为-1 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <string> 10 #include <stack> 11 #in

Codeforces Round #304 (Div. 2)——1002—— Soldier and Badges

Colonel has n badges. He wants to give one badge to every of his n soldiers. Each badge has a coolness factor, which shows how much it's owner reached. Coolness factor can be increased by one for the cost of one coin. For every pair of soldiers one o

Codeforces Round #304 (Div. 2)——Cdfs——Soldier and Cards

Two bored soldiers are playing card war. Their card deck consists of exactly n cards, numbered from 1 to n, all values are different. They divide cards between them in some manner, it's possible that they have different number of cards. Then they pla

codeforces水题100道 第五题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas (math)

题目链接:http://www.codeforces.com/problemset/problem/546/A题意:一个人现在有n元,它买第i根香蕉需要i*k元,问他要买w根香蕉的话,需要问他的朋友借多少钱?C++代码: #include <iostream> using namespace std; int n, k, w; int main() { cin >> k >> n >> w; cout << max(0, w*(w+1)/2*k-

Codeforces Round #304 (Div. 2) -----CF546

A. Soldier and Bananas A soldier wants to buy w bananas in the shop. He has to pay k dollars for the first banana, 2k dollars for the second one and so on (in other words, he has to pay i·k dollars for the i-th banana). He has n dollars. How many dol