题意

给定 n 个城市,m 条边。人只能从走相邻边相连(只能走一次)的城市。

现在给你初始城市的每一个人数,再给一组每个城市人数。询问是否可以从当前人数变换到给定人数。如果能,输入“YES”并输出方案,不能则输出“NO”。

http://codeforces.com/contest/546/problem/E

思路

当∑a!=∑b时,肯定不能。

建一个超级源点s和超级汇点t,s到(1n)连一条容量为a[i]的边,(n+12*n)到t连一条容量为b[i]的边,再将图中给定相连的边连容量为inf的边,比如u和v相连,那么u到v+n和v到u+n都要连容量为inf的边。还要将自己跟自己连边,即i到i+n连一条容量为inf的边,因为自己点的人不走相当于自己点走到自己点。最后都连上反向边用Dinic跑最大流,如果最大流==∑a,那么能,方案可以根据i到i+n的反向边的流量来求解。

样例的建图类似下面这样(随便画的):

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
const int N=505;
int n,m,x,y,z,maxflow,deep[N];//deep深度
struct Edge
{
int next,to,dis;
} edge[N*10];
int num_edge=-1,head[N],cur[N];//cur用于复制head
queue <int> q; void add_edge(int from,int to,int dis,bool flag)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
if (flag) edge[num_edge].dis=dis;//反图的边权为 0
head[from]=num_edge;
} //bfs用来分层
bool bfs(int s,int t)
{
memset(deep,0x7f,sizeof(deep));
while (!q.empty()) q.pop();
for (int i=0; i<=2*n+1; i++) cur[i]=head[i];
deep[s]=0;
q.push(s); while (!q.empty())
{
int now=q.front();
q.pop();
for (int i=head[now]; i!=-1; i=edge[i].next)
{
if (deep[edge[i].to]>inf && edge[i].dis)//dis在此处用来做标记 是正图还是返图
{
deep[edge[i].to]=deep[now]+1;
q.push(edge[i].to);
}
}
}
if (deep[t]<inf) return true;
else return false;
} //dfs找增加的流的量
int dfs(int now,int t,int limit)//limit为源点到这个点的路径上的最小边权
{
if (!limit || now==t) return limit; int flow=0,f;
for (int i=cur[now]; i!=-1; i=edge[i].next)
{
cur[now]=i;
if (deep[edge[i].to]==deep[now]+1 && (f=dfs(edge[i].to,t,min(limit,edge[i].dis))))
{
flow+=f;
limit-=f;
edge[i].dis-=f;
edge[i^1].dis+=f;
if (!limit) break;
}
}
return flow;
} void Dinic(int s,int t)
{
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
int a[N],b[N];
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
int s1=0,s2=0,s=0,t=2*n+1;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
add_edge(s,i,a[i],1);
add_edge(i,s,a[i],0);
s1+=a[i];
}
for(int i=1; i<=n; i++)
{
scanf("%d",&b[i]);
add_edge(i+n,t,b[i],1);
add_edge(t,i+n,b[i],0);
s2+=b[i];
}
for (int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
add_edge(x,y+n,inf,1);
add_edge(y+n,x,inf,0);
add_edge(y,x+n,inf,1);
add_edge(x+n,y,inf,0);
}
if(s1!=s2)
{
puts("NO");
return 0;
}
for(int i=1;i<=n;i++)
{
add_edge(i,i+n,inf,1);add_edge(i+n,i,inf,0);
}
Dinic(s,t);
// cout<<maxflow<<endl;
if(maxflow==s1)
{
puts("YES");
int g[N][N];
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=edge[j].next)
{
int v=edge[j].to;
if(v>n)
{
g[i][v-n]=edge[j^1].dis;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
printf("%d ",g[i][j]);
}
puts("");
}
}
else
{
puts("NO");
}
return 0;
}

Codeforces Round #304 (Div. 2)(CF546E) Soldier and Traveling(最大流)的更多相关文章

  1. Codeforces Round #304 (Div. 2) E. Soldier and Traveling 最大流

    题目链接: http://codeforces.com/problemset/problem/546/E E. Soldier and Traveling time limit per test1 s ...

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

    题目传送门 /* 题意:b+1,b+2,...,a 所有数的素数个数和 DP+埃氏筛法:dp[i] 记录i的素数个数和,若i是素数,则为1:否则它可以从一个数乘以素数递推过来 最后改为i之前所有素数个 ...

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

    题目传送门 /* 题意:两堆牌,每次拿出上面的牌做比较,大的一方收走两张牌,直到一方没有牌 queue容器:模拟上述过程,当次数达到最大值时判断为-1 */ #include <cstdio&g ...

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

    题目传送门 /* 题意:问最少增加多少值使变成递增序列 贪心:排序后,每一个值改为前一个值+1,有可能a[i-1] = a[i] + 1,所以要 >= */ #include <cstdi ...

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

    题目传送门 /* 水题:ans = (1+2+3+...+n) * k - n,开long long */ #include <cstdio> #include <algorithm ...

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

    题目传送门 /* 题意:这题就是求b+1到a的因子个数和. 数学+DP:a[i]保存i的最小因子,dp[i] = dp[i/a[i]] +1;再来一个前缀和 */ /***************** ...

  7. Codeforces Round #304 (Div. 2) D. Soldier and Number Game 数学 质因数个数

    D. Soldier and Number Game Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/conte ...

  8. Codeforces Round #304 (Div. 2) C. Soldier and Cards 水题

    C. Soldier and Cards Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/546 ...

  9. Codeforces Round #304 (Div. 2) B. Soldier and Badges 水题

    B. Soldier and Badges Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/54 ...

随机推荐

  1. django DeleteView

    DeleteView from django.urls import reverse, reverse_lazy from django.contrib.auth.mixins import Logi ...

  2. table表格属性

  3. es6 的类 class

    1.ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类. 2. //定义类 class Point { constructor(x, y ...

  4. shell的几个实战脚本例子(欠)

    如何让shell实现 可选择性执行 的功能 巡检内存使用率 批量创建用户 场景:公司想要做测试,需要10000个用户 数据库里查询学生成绩 #如何登录mysql数据库 #如何写sql对数据进行操作 # ...

  5. Python tempfile (临时文件)

    Python tempfile 大量临时数据放在内存中会占用大量资源,可以使用临时文件来进行储存 临时文件不用命名,且使用后会被自动删除 TemporaryFile 使用 TemporaryFile ...

  6. Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2) F. Tree Factory 构造题

    F. Tree Factory Bytelandian Tree Factory produces trees for all kinds of industrial applications. Yo ...

  7. linux下如何查看自己都装了什么服务

    service --status-all 先把rabbitmq进程杀掉 ps -ef | grep rabbitmq | grep -v grep | awk '{print $2}' | xargs ...

  8. strcasecmp()函数

    函数介绍: strcasecmp用忽略大小写比较字符串.,通过strcasecmp函数可以指定每个字符串用于比较的字符数,strncasecmp用来比较参数s1和s2字符串前n个字符,比较时会自动忽略 ...

  9. DirectShow 学习方法

    DirectShow(简称 DShow) 是一个 Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能. 这篇博客主要是简单讲下如何学习 Direct Show 框架,避免让自己少 ...

  10. 解决python3.7 ModuleNotFoundError: No module named bz2

    解决: ModuleNotFoundError: No module named  bz2 ModuleNotFoundError: No module named '_lzma' 1.在操作系统中安 ...