CDOJ 1962 天才钱vs学霸周2【最大流】
以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【最大流】的更多相关文章
- 矩阵解压,网络流UESTC-1962天才钱vs学霸周2
天才钱vs学霸周2 Time Limit: 500 MS Memory Limit: 128 MB Submit Status 由于上次的游戏中学霸周输了,因此学霸周想出个问题为难天才钱,问题 ...
- 最小生成树唯一性判断-UESTC1959天才钱vs学霸周
天才钱vs学霸周 Time Limit: 1000 MS Memory Limit: 256 MB Submit Status 有一天,天才钱和学霸周闲的无聊玩起了游戏,游戏内容是这样的,现在 ...
- 度及拓扑图的使用-UESTC1958学霸周选课
学霸周选课 Time Limit: 1000 MS Memory Limit: 128 MB Submit Status 众所周知周大爷不仅编程了得,专业课成绩更是名列前茅,恰巧又到了选课的季 ...
- 【P1379】天才的约数和
来自GDOI2007,原题已不可考-- 又自己做出来了好开心,找特殊性是个关键的切入点 原题: 这天周航遇到了靳泽旭. 周航:"我是天才!" 靳泽旭:"你为什么是天才?& ...
- Python-week2,第二周(基于Python3.0以上)
1,列表 存储数据我们可以使用变量,但是当有很多个数据的时候用变量就会出现很多的局限性,所以这时候就用到了列表.列表就是中括号里每个元素使用逗号隔开.列如 [1,2,3] 这就是一个列 ...
- 【Win 10 应用开发】获取本机的IP地址
按照老规矩,也是朋友的建议,老周今天在吹牛之前,先讲一个小故事. 有朋友问我,老周,你现在还发短信吗,你每个月用多少电话费?唉,实话说,现在真的发短信不多了,套餐送的130条短信,每月都发不了一条.至 ...
- java List的排序
List自定义排序 1.第一种方法,就是list中对象实现Comparable接口,重写compareTo接口, 对排序的字段进行比较.2.第二种方法,就是在重载Collections.sort方法. ...
- js 随机生成姓名、手机号、身份证号、银行卡号
开发测试的时候,经常需要填写姓名.手机号.身份证号.银行卡号,既要符合格式要求.又不能重复.大家会到网上搜各种生成器.能不能自己写一个简单的生成器呢.下面是随机生成姓名.手机号.身份证号.银行卡号的j ...
- C# 写的一个生成随机汉语名字的小程序
最近因为要做数据库相关的测试,频繁使用到测试数据,手动添加太过于麻烦,而且复用性太差,因此干脆花了点时间写了一个生成随机姓名和相关数据的类,贴在这里,有需用的同志们可以参考一下.代码本身质量不好,也不 ...
随机推荐
- python3+selenium框架设计10-发送邮件
使用python3的email模块和smtplib模块可以实现发送邮件的动能.email模块用来生成email,smtplib模块用来发送邮件,接下来看如何在生成测试报告之后,并将报告放在邮件附件中并 ...
- 在 C# 中,(int) ,Int32.Parse() 和 Convert.toInt32() 三种方法的区别
在 C# 中,(int),Int32.Parse() 和 Convert.toInt32() 三种方法有何区别? int 关键字表示一种整型,是32位的,它的 .NET Framework 类型为 S ...
- Power Network POJ - 1459 [网络流模板]
http://poj.org/problem?id=1459 嗯,网络流模板...多源点多汇点的图,超级汇点连发电厂,用户连接超级汇点 Status Accepted Time 391ms Memor ...
- ffmpeg 增加视频流媒体质量评估滤镜 (Video Multimethod Assessment Fusion, VMAF)
URL: https://github.com/Netflix/vmaf libvmaf Obtain the VMAF (Video Multi-Method Assessment Fusion) ...
- YCSB之HBase性能测试
1.YCSB背景 YCSB,全称为“Yahoo!Cloud Serving Benchmark”,是雅虎开发的用来对云服务进行基础测试的工具,其内部涵盖了常见的NoSQL数据库产品,如Cassandr ...
- Tornado学习笔记(三) 请求方式/状态码
本章我们来学习 Tornado 支持的请求方式 请求方式 Tornado支持任何合法的HTTP请求(GET.POST.PUT.DELETE.HEAD.OPTIONS).你可以非常容易地定义上述任一种方 ...
- C#中lock死锁实例教程
这篇文章主要介绍了C#中lock死锁的用法,对于共享资源的访问及C#程序设计的安全性而言,有着非常重要的意义!需要的朋友可以参考下 链接:http://www.jb51.net/article/543 ...
- iOS -- Effective Objective-C 阅读笔记 (3)
1: 理解 属性 的概念 属性会自动生成存取方法, 可以利用点语法调用, 若不想编译器自动合成存取方法, 可以自己实现, 还有另外一种方法, 就是使用 @dynamic 关键字, 它会告诉编译器, ...
- Confluence 6 手动备份站点
Confluence 被配置自动备份数据,使用压缩的 XML 格式.同时你也可以通过 Confluence 的 管理员控制台(Administration Console)手动进行备份. 你需要具有 ...
- Confluence 6 SQL Server 数据库驱动修改
从 Confluence 6.4 开始,我们使用官方的 Microsoft SQL Server JDBC 驱动来替换掉开源的 jTDS 驱动.从这个版本开始所有的安装都会默认使用官方的 Micros ...