zoukankan      html  css  js  c++  java
  • Codeforces 546 E:士兵的旅行 最大网络流

    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 atmoving 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


    51nod上也有这道题,题意就是:

    在某个国家有n个城市,他们通过m条无向的道路相连。每个城市有一支军队。第i个城市的军队有ai个士兵。现在士兵开始移动。每个士兵可以呆在原地,或者走到和他所在城市直接相邻的城市,即设每一条边长度为1的话,他离开之后不能距离原来城市大于1。

    判断移动之后,能不能使得第i个城市恰好有bi个士兵。


    (......)

    发现题目一旦像这种有一堆点的起始状态,然后是目标状态的,并且可以用路径来更改每个点的状态的。这种题用最大网络流做准没错。

    1.将源点与各个点相连,容量就是a[i]。

    2.将汇点与各个点相连,容量就是b[i]。

    3.将a[i]与a[i+N]相连,容量是INF,表示士兵可以留在自己的城市里面。

    4.对于两个城市i与j有边的,将i与j+N相连,将j与i+N相连,容量均为INF,表示士兵可以从这两个城市来回窜。

    5.求一下最大流,保证最大流填满了源点的每一条管道,填满了汇点的每一条管道。即最大流等于a[i]之和,也等于b[i]之和,就是YES。否则就是NO。


    代码:

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <queue>
    #pragma warning(disable:4996)
    using namespace std;
    
    const int sum = 205;
    const int INF = 99999999;
    
    int cap[sum][sum], flow[sum][sum], a[sum], p[sum];
    int val[1005];
    int flag[1005];
    int sum1, sum2;
    int N, M;
    
    void Edmonds_Karp()
    {
    	int u, t, result = 0;
    	queue <int> s;
    	while (s.size())s.pop();
    
    	while (1)
    	{
    		memset(a, 0, sizeof(a));
    		memset(p, 0, sizeof(p));
    
    		a[0] = INF;
    		s.push(0);
    
    		while (s.size())
    		{
    			u = s.front();
    			s.pop();
    
    			for (t = 0; t <= M + 1; t++)
    			{
    				if (!a[t] && flow[u][t]<cap[u][t])
    				{
    					s.push(t);
    					p[t] = u;
    					a[t] = min(a[u], cap[u][t] - flow[u][t]);//要和之前的那个点,逐一比较,到M时就是整个路径的最小残量  
    				}
    			}
    		}
    		if (a[M + 1] == 0)
    			break;
    		result += a[M + 1];
    
    		for (u = M + 1; u != 0; u = p[u])
    		{
    			flow[p[u]][u] += a[M + 1];
    			flow[u][p[u]] -= a[M + 1];
    		}
    	}
    	if (sum1 == result&&sum2 == result)
    	{
    		cout << "YES" << endl;
    		int i, j;
    		for (i = 1; i <= M/2; i++)
    		{
    			for (j = 1; j <= M/2; j++)
    			{
    				if (j == 1)
    				{
    					cout << flow[i][j + M/2];
    				}
    				else
    				{
    					cout <<" "<<flow[i][j + M/2];
    				}
    			}
    			cout << endl;
    		}
    	}
    	else
    	{
    		cout << "NO" << endl;
    	}
    }
    
    int main()
    {
    	//freopen("i.txt","r",stdin);
    	//freopen("o.txt","w",stdout);
    
    	int i, temp, temp1, temp2;
    	cin >> N >> M;
    	
    	sum1 = 0; 
    	sum2 = 0;
    	memset(cap, 0, sizeof(cap));
    	for (i = 1; i <= N; i++)
    	{
    		cin >> temp;
    		cap[0][i] = temp;
    		sum1 += temp;
    	}
    	for (i = 1; i <= N; i++)
    	{
    		cin >> temp;
    		cap[i + N][2 * N + 1] = temp;
    		sum2 += temp;
    
    		cap[i][i + N] = INF;
    	}
    	for (i = 1; i <= M; i++)
    	{
    		cin >> temp1 >> temp2;
    		cap[temp1][temp2 + N] = INF;
    		cap[temp2][temp1 + N] = INF;
    	}
    	M = 2 * N ;
    	Edmonds_Karp();
    	
    	//system("pause");
    	return 0;
    }
    




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

  • 相关阅读:
    Tips_of_JS 之 利用JS实现水仙花数的寻找与实现斐波那契数列
    我的天!居然可以这么“弹”!—— 弹性盒布局属性详述
    震惊,正儿八经的网页居然在手机上这样显示!
    这是假的JS——利用CSS Animation实现banner图非交互循环播放
    小K的H5之旅-HTML5与CSS3部分新属性浅见
    CSS小技巧-煎蛋的画法~
    小K的H5之旅-实战篇(一)
    SSM+Redis简介
    Hadoop HA(高可用搭建)
    hadoop完全分布式搭建(非高可用)
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4928125.html
Copyright © 2011-2022 走看看