codeforces 546 E Soldier and Traveling

传送门

题意:给你初始状态和目标状态,再给你m条路,士兵只能通过路走到相邻城市去,一个士兵只能移动一次。问你能否到达该状态,如果能输出转移的矩阵

题解:很显然的网络流,将一个点拆成三个,一个初始状态与s连,一个目标状态与t连,容量b[i],在建立一个中间点,连接初始状态容量INF和目标状态容量a[i];记录下每个中间点和相邻点的边,再跑完网络流后,原容量减去残余流量就能得到转移的士兵个数

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
//CLOCKS_PER_SEC
#define se second
#define fi first
#define ll long long
#define Pii pair<int,int>
#define Pli pair<ll,int>
#define ull unsigned long long
#define pb push_back
#define fio ios::sync_with_stdio(false);cin.tie(0)
const double Pi=3.14159265;
const int N=1e6+10;
const ull base=163;
const int INF=0x3f3f3f3f;
using namespace std;
int n,m,s,t,tot=0;
int head[900],nx[N],to[N],cap[N],cur[900];
void add(int u,int v,int c){
    to[tot]=v;
    nx[tot]=head[u];
    cap[tot]=c;
    head[u]=tot++;

    to[tot]=u;
    nx[tot]=head[v];
    cap[tot]=0;
    head[v]=tot++;
}
int d[900];
bool bfs(){
    memset(d,-1,sizeof(d));
    queue<int>q;
    q.push(s);
    d[s]=1;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=nx[i]){
            int v=to[i];
            if(d[v]==-1&&cap[i]>0){
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }

    return d[t]!=-1;
}
int dfs(int s,int a){
    if(s==t||a==0)return a;
    int flow=0,f;
    for(int &i=cur[s];~i;i=nx[i]){
        int v=to[i];
        if(d[s]+1==d[v] && cap[i]>0 && (f=dfs(v,min(a,cap[i])))>0){
            flow+=f;
            cap[i]-=f;
            cap[i^1]+=f;
            a-=f;
            if(a==0)break;
        }
    }
    return flow;
}
int dinic(){
    int ans=0;
    while(bfs()){
        for(int i=0;i<=t;i++)cur[i]=head[i];
        while(int di=dfs(s,INF)){
            ans+=di;
        }
    }
    return ans;
}
int a[900],b[900];
int num[200][200];
pair<int,int>p[900];
int po[600];
int main(){
    scanf("%d%d",&n,&m);
    t=600,s=0;
    memset(head,-1,sizeof(head));
    int o=0;
    int oo=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        oo+=a[i];
        add(s,i,a[i]);
        num[i][i]=a[i];
        add(i,i+n,INF);
        add(i+n,i+2*n,a[i]);
    }
    int sum=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
        add(i+2*n,t,b[i]);
        sum+=b[i];
    }

    for(int i=1;i<=m;i++){
        int u,v;scanf("%d%d",&u,&v);
        add(u+n,v+2*n,a[u]);
        p[++o].fi=u+n,p[o].se=v+2*n;
        po[o]=tot-2;
        add(v+n,u+2*n,a[v]);
        p[++o].fi=v+n,p[o].se=u+2*n;
        po[o]=tot-2;
    }
    int ans=dinic();
    if(ans!=sum||oo!=sum)return cout<<"NO\n",0;
    else {
        cout<<"YES\n";
        for(int i=1;i<=o;i++){
            int x=a[p[i].fi-n]-cap[po[i]];
            if(x>0){
                num[p[i].fi-n][p[i].se-2*n]+=x;
                num[p[i].fi-n][p[i].fi-n]-=x;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cout<<num[i][j]<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Mrleon/p/9136526.html

时间: 2024-10-11 16:09:21

codeforces 546 E Soldier and Traveling的相关文章

网络流(最大流) CodeForces 546E:Soldier and Traveling

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 neighb

CodeForces 546 A - Soldier and Bananas

题目链接:click here~~ [题目大意] 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 d

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 ci

Codeforces 546E Soldier and Traveling(最大流)

题目大概说一张无向图,各个结点初始有ai人,现在每个人可以选择停留在原地或者移动到相邻的结点,问能否使各个结点的人数变为bi人. 如此建容量网络: 图上各个结点拆成两点i.i' 源点向i点连容量ai的边 i'向汇点连容量bi的边 i向i'连容量INF的边 对于相邻的两点(u,v),u向v'连容量INF的边,v'向u连容量INF的边 跑最大流看看最大流是否等于∑bi.另外,注意∑ai不等于∑bi的情况. 1 #include<cstdio> 2 #include<cstring> 3

CodeForces 546E - Soldier and Traveling(最大流+输出边流量)

题目链接:click here~~ [题目大意]:给定一些城市里面原先状态的士兵数目,和某些城市之间的联通关系,求能否达到最终状态. [解题思路]做完这套题,感觉这道题是五个题里最有质量的题了,搞了差不多一天半的时间,开始很难想到构图,想到了是最大流之后,又卡在了输出流量上,w(?Д?)w,还是这类题做的太少,~~~~(>_<)~~~~!首先比较很难构想到最大流,但是抓住题目关键,仔细想想也不难,好,想到了是构造最大流,那么接下来难点是建源点,汇点,剩下的就是套模板了,弱弱的献上代码,欢迎各位

codeforces 546E. Soldier and Traveling 网络流

题目链接 给出n个城市, 以及初始时每个城市的人数以及目标人数.初始时有些城市是相连的. 每个城市的人只可以待在自己的城市或走到与他相邻的城市, 相邻, 相当于只能走一条路. 如果目标状态不可达, 输出no, 否则输出每个城市的人都是怎么走的, 比如第一个城市有2个人走到了第二个城市, 1个人留在了第一个城市, 那么输出的第一行前两个数就是1, 2. 很明显的网络流, 输出那里写了好久... 首先判断能否可达, 如果初始状态的人数与目标状态不一样, 一定不可达, 其次, 如果建完图跑网络流的结果

Codeforces D546:Soldier and Number Game

题目链接:http://codeforces.com/problemset/problem/546/D 输入t对数 a, b 求(b,a]内的每个数拆成素因子的个数和 这里每个数都可以写成素数的乘积,可以写成几个素数的和就有几个素因子,这里求的是(b,a]内的素因子和 思路: 素数的素因子个数是1 对于非素数A的素因子个数 = A/k  + 1 其中k是素数,也是第一个素数,或者K是比A小的数,并且A%k==0 下面是利用K是比A小的数,并且A%k==0 1 void solve(){ 2 Sc

CF546E Soldier and Traveling

题目描述 In the country there are n n n cities and m m m bidirectional roads between them. Each city has an army. Army of the i i i -th city consists of ai a_{i} ai? soldiers. Now soldiers roam. After roaming each soldier has to either stay in his city o

【CodeForces - 546C】Soldier and Cards (vector或队列)

Soldier and Cards 老样子,直接上国语吧  Descriptions: 两个人打牌,从自己的手牌中抽出最上面的一张比较大小,大的一方可以拿对方的手牌以及自己打掉的手牌重新作为自己的牌,放在自己手牌的最下方,而且对方输掉的那张手牌需要放在上面,自己赢的手牌放在下面. Input 第一行的数n代表一共有几张牌 第二行第一个数x代表第一个人有x张牌 第三行第一个数y代表第二个人有y张牌 Output 第一个数代表进行了几轮,第二个数代表谁赢 Examples Input 42 1 32