题意

给定 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. 简单web服务工作流程梳理

       一.用户访问web基本流转过程梳理 二.web框架粗略概括

  2. 自定义MVC二

    1. 什么是MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写, 它是一种软件设计典范,用一种业务逻辑.数据. ...

  3. 线程让步yield

    一.yield()的作用 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并不能保证在当前线程调用yield()之后,其 ...

  4. LG2921 [USACO2008DEC]Trick or Treat on the Farm 内向基环树

    问题描述 LG2921 题解 发现一共有 \(n\) 个点,每个点只有一条出边,即只有 \(n\) 条边,于是就是一个内向基环树. \(\mathrm{Tarjan}\) 缩点. 但是这个题比较猥琐的 ...

  5. 无法用排他锁锁定该数据库,以执行该操作。 (Microsoft SQL Server,错误: 5030)

    ALTER DATABASE Test_DB modify name = Howie --更改数据库名 EXEC sp_renamedb 'Howie' , 'Howie_Wee' --更改数据库名 ...

  6. 10.7 csp-s模拟测试63 Median+Game+Park

    我堕落了 我觉得任牛逼的问题也是我的问题 T1 Median T2 Game T3 Park

  7. 宝塔面板+djiango+mod wsgi +apache 配置多项目站点

    在一台服务器上同时有多个djiango项目,那么就需要配置多站点,利用不同的域名不同的端口  同时存在多个项目. 环境,centos + 宝塔面板+apache+django 1.在centos环境下 ...

  8. 小小见解之python循环依赖

    a.py from b import b print '---------this is module a.py----------' def a(): print "hello, a&qu ...

  9. D3力布图绘制--节点跑掉,单曲线弯曲问题记录

    D3力布图绘制中遇到的交互问题,频繁操作数据后,会出现节点跑掉和单曲线弯曲的问题 问题描述 在id指向都正常的情况下出现以下2种状况: 单曲线弯曲 节点跑掉 经排查,是数据重复导致的问题 线条也是一样 ...

  10. 缘起 Dubbo ,讲讲 Spring XML Schema 扩展机制

    背景 在 Dubbo 中,可以使用 XML 配置相关信息,也可以用来引入服务或者导出服务.配置完成,启动工程,Spring 会读取配置文件,生成注入 相关 Bean.那 Dubbo 如何实现自定义 X ...