以s=0,t=n+m+1分别为超级源点和超级汇点。网络流中的流量以0为开始,题目要求从1到20,我们先把每个点都减去1,即ai - m,bi - n。然后源点s与n个顶点连容量为ai的路,汇点t与m个顶点连容量为bi的路,n个顶点再与m个顶点连接19的容量。最后再跑下Dinic,如果最后汇聚到t的流量和总值相同,输出“Yes”,否则输出“No”。最后输出对应边的答案,可以用残余网络来计算,用19-残余的容量即该条边的流量。

 #include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int N=;
const int M=N*N;
const int INF = 0x3f3f3f3f;
int s,t,n,m,cnt;
int a[N],b[N];
int Head[N],Depth[N],Next[M],V[M],W[M]; void init()
{
cnt=-;
memset(Head,-,sizeof(Head));
memset(Next,-, sizeof(Next));
} void add_edge(int u,int v,int w)
{
cnt++;Next[cnt]=Head[u];V[cnt]=v;W[cnt]=w;Head[u]=cnt;
cnt++;Next[cnt]=Head[v];V[cnt]=u;W[cnt]=;Head[v]=cnt; // 反向边
} bool bfs()
{
queue<int> q;
while(!q.empty())q.pop();
memset(Depth,, sizeof(Depth));
q.push(s);
Depth[s]=;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=Head[u];i!=-;i=Next[i])
{
if(W[i]>&&Depth[V[i]]==)
{
Depth[V[i]]=Depth[u]+;
q.push(V[i]);
}
}
}
if(Depth[t]==)return false;
else return true;
} int dfs(int u,int flow)
{
if(u==t)return flow;
int rest = flow;
for(int i=Head[u];i!=-;i=Next[i])
{
if(Depth[V[i]]==Depth[u]+&&W[i]>)
{
int k=dfs(V[i],min(W[i],rest));
if(!k)Depth[V[i]]=; // 剪枝,去掉增广完毕的点
W[i]-=k;
W[i^]+=k;
rest-=k;
}
}
return flow-rest;
} int Dinic()
{
int ans=;
while(bfs()) // 在残量网络上构造分层图
{
while(int flow = dfs(s,INF)) // 在当前分层图上增广
ans+=flow;
}
return ans;
} void print()
{
int res[N][N];
memset(res,,sizeof(res));
for(int i=;i<=n;i++)
for(int j=Head[i];j!=-;j=Next[j])
{
int v=V[j];
if(v>n&&v<=n+m)res[i][v-n]=-W[j]+;
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
printf("%d",res[i][j]);
if(j==m) printf("\n");
else printf(" ");
}
}
} int main(){
init();
scanf("%d%d",&n,&m);
s=;t=n+m+; for(int i=;i<=n;i++){
scanf("%d",&a[i]);a[i]-=m;
add_edge(s,i,a[i]);
}
for(int i=;i<=m;i++){
scanf("%d",&b[i]);b[i]-=n;
add_edge(n+i,t,b[i]);
} for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
add_edge(i,n+j,); int c1=,c2=,c3=;
for(int i=;i<=n;i++) c1+=a[i];
for(int i=;i<=m;i++) c2+=b[i];
if(c1!=c2) printf("No\n");
else{
c3=Dinic();
if(c3!=c2) printf("No\n");
else{
printf("Yes\n");
print();
}
}
return ;
}

附:Edmonds-Karp增广路算法模板: 不断用BFS寻找增广路,直至网络上不存在增广路为止

 const int inf = <<,N=,M=;
int head[N],ver[M],edge[M],Next[M],v[N],incf[N],pre[N];
int n,m,s,t,tot,maxflow; void add(int x,int y,int z)
{
tot++,ver[tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot; // 邻接表的数组写法
tot++,ver[tot]=x,edge[tot]=,Next[tot]=head[y],head[y]=tot; //反向边,edge剩余容量
} bool bfs()
{
memset(v,, sizeof(v));
queue<int> q;
q.push(s);v[s]=;
incf[s]=inf; // 增广路上个边的最小剩余容量
while(q.size())
{
int x = q.front();
q.pop();
for(int i=head[x];i;i=Next[i])
{
if(edge[i])
{
int y=ver[i];
if(v[y])continue;
incf[y]=min(incf[x],edge[i]);
pre[y]=i; // 记录前驱(当前的tot序号,偶奇成对存储,抑或操作可导出前驱)
q.push(y);
v[y]=;
if(y==t)return ; // 可达t点
}
}
}
return ;
} void update()// 更新一条增广路及其反向边的剩余容量
{
int x = t;
while(x!=s)
{
int i=pre[x];
edge[i]-=incf[t];
edge[i^]+=incf[t];
x = ver[i^]; // 前驱节点
}
maxflow+=incf[t];
} int main()
{
while(cin>>m>>n)
{
memset(head,, sizeof(head));
s=,t=n;tot=;maxflow=;
for(int i=;i<=m;i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
add(x,y,c);
}
while(bfs())update();
cout<<maxflow<<endl;
}
}

CDOJ 1962 天才钱vs学霸周2【最大流】的更多相关文章

  1. 矩阵解压,网络流UESTC-1962天才钱vs学霸周2

    天才钱vs学霸周2 Time Limit: 500 MS     Memory Limit: 128 MB Submit Status 由于上次的游戏中学霸周输了,因此学霸周想出个问题为难天才钱,问题 ...

  2. 最小生成树唯一性判断-UESTC1959天才钱vs学霸周

    天才钱vs学霸周 Time Limit: 1000 MS     Memory Limit: 256 MB Submit Status 有一天,天才钱和学霸周闲的无聊玩起了游戏,游戏内容是这样的,现在 ...

  3. 度及拓扑图的使用-UESTC1958学霸周选课

    学霸周选课 Time Limit: 1000 MS     Memory Limit: 128 MB Submit Status 众所周知周大爷不仅编程了得,专业课成绩更是名列前茅,恰巧又到了选课的季 ...

  4. 【P1379】天才的约数和

    来自GDOI2007,原题已不可考-- 又自己做出来了好开心,找特殊性是个关键的切入点 原题: 这天周航遇到了靳泽旭. 周航:"我是天才!" 靳泽旭:"你为什么是天才?& ...

  5. Python-week2,第二周(基于Python3.0以上)

    1,列表 存储数据我们可以使用变量,但是当有很多个数据的时候用变量就会出现很多的局限性,所以这时候就用到了列表.列表就是中括号里每个元素使用逗号隔开.列如     [1,2,3]     这就是一个列 ...

  6. 【Win 10 应用开发】获取本机的IP地址

    按照老规矩,也是朋友的建议,老周今天在吹牛之前,先讲一个小故事. 有朋友问我,老周,你现在还发短信吗,你每个月用多少电话费?唉,实话说,现在真的发短信不多了,套餐送的130条短信,每月都发不了一条.至 ...

  7. java List的排序

    List自定义排序 1.第一种方法,就是list中对象实现Comparable接口,重写compareTo接口, 对排序的字段进行比较.2.第二种方法,就是在重载Collections.sort方法. ...

  8. js 随机生成姓名、手机号、身份证号、银行卡号

    开发测试的时候,经常需要填写姓名.手机号.身份证号.银行卡号,既要符合格式要求.又不能重复.大家会到网上搜各种生成器.能不能自己写一个简单的生成器呢.下面是随机生成姓名.手机号.身份证号.银行卡号的j ...

  9. C# 写的一个生成随机汉语名字的小程序

    最近因为要做数据库相关的测试,频繁使用到测试数据,手动添加太过于麻烦,而且复用性太差,因此干脆花了点时间写了一个生成随机姓名和相关数据的类,贴在这里,有需用的同志们可以参考一下.代码本身质量不好,也不 ...

随机推荐

  1. vue 选城市三级联动

    <div id="example"> <select v-model="prov"> <option v-for="op ...

  2. Boost property_tree解析json

    使用Boost property_tree解析json 之前使用jsoncpp解析json,现在才知道boost就有解析的库,学习一下吧 property_tree可以解析xml,json,ini,i ...

  3. Centos 6.x/7.x yum安装php5.6.X(最新版)

    鉴于Centos 默认yum源的php版本太低了,手动编译安装又有点一些麻烦,那么如何采用Yum安装的方案安装最新版呢.那么,今天我们就来学习下如何用yum安装php最新版. 1.检查当前安装的PHP ...

  4. bigfile tablespace

    背景       这次终于有个linux实际迁移oracle的机会了,之前都是学习实验.想起最早时,都是windows搞oracle,又让我想起多年期一个项目,数据量太大及计算逻辑太复杂,我用存储过程 ...

  5. 第八次作业(课堂实战)- 项目UML设计(团队)

    1. 团队信息 队名:小白吃队 成员: 后敬甲 031602409 卢泽明 031602328 蔡文斌 031602301 葛亮 031602617 刘浩 031602423 黄泽 031602317 ...

  6. ansible笔记(7):常用模块之系统类模块

    ansible笔记():常用模块之系统类模块 cron模块 cron模块可以帮助我们管理远程主机中的计划任务,功能相当于crontab命令. 在了解cron模块的参数之前,先写出一些计划任务的示例,示 ...

  7. C/C++ 获取文件大小

    在C语言中测试文件的大小,主要使用二个标准函数. 1.fseek 函数原型:int fseek ( FILE * stream, long int offset, int origin ); 参数说明 ...

  8. eclipse的工程中如何查找字符串

    ctrl + h 后弹出 tab选项, 你选择 file search 然后在下面输入要查找的字符串 workset 那里选择你要查找的项目 默认是全部项目进行查找

  9. python字符串str和字节数组bytes相互转化

    1 引言 后续待补充 2 代码 b = b"Hello, world!" # bytes s = "Hello, world!" # string print( ...

  10. 判断js数据类型的四种方法,以及各自的优缺点(转)

    转载地址:https://blog.csdn.net/lhjuejiang/article/details/79623973 数据类型分为基本类型和引用类型: 基本类型:String.Number.B ...