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# 写的一个生成随机汉语名字的小程序
最近因为要做数据库相关的测试,频繁使用到测试数据,手动添加太过于麻烦,而且复用性太差,因此干脆花了点时间写了一个生成随机姓名和相关数据的类,贴在这里,有需用的同志们可以参考一下.代码本身质量不好,也不 ...
随机推荐
- cryptsetup文件系统加密
今天做了SYC攻防题的文件系统挂载部分,在找到挂载最内层的final文件时发现mount无法识别,这也许就是一个加密的文件系统吧,还好-在龟速的 网络环境下查阅到了losetup循环挂载系统命令,但是 ...
- $Djangon admin界面 添加表 增删查改
from django.contrib import admin表变中文 class Meta: verbose_name_plural='评论表' null=True的字段:admin创建要求写可以 ...
- 前端 -----jQuery的选择器
02-jQuery的选择器 我们以前在CSS中学习的选择器有: 今天来学习一下jQuery 选择器. jQuery选择器是jQuery强大的体现,它提供了一组方法,让我们更加方便的获取到页面中的元 ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 备注和问题解决
备注 在创建证书时候的背景信息: 'keytool -genkeypair' 命令将会创建秘钥对,包括公钥和关联的私钥,然后存储到 keystore 中.这个命令打包公钥为 X.509 v3 自签 ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 重定向所有的 URLS 到 HTTPS 的安全考虑
尽管现在 HTTPS 现在已经激活并且可用了.老的 HTTP URLs (http://localhost:8090)还是可以访问的.现在你需要重定向所有 URLs 到他们的 HTTPS 链接中.你可 ...
- Jquery如何获取iframe里面body的html呢?
如果是自己网页的话,可以这样,$("iframe").contents().find("body").html();意思是,获取iframe里面页面body的内 ...
- 团队开发工具git常用命令
Git 常用命令 Git配置 git config --global user.name "storm" git config --global user.email " ...
- 【kafka】设置指定topic和group_id消耗的offset
该博文方法有问题,正确方案在http://www.cnblogs.com/dplearning/p/7992994.html 背景: 搭建了一个kafka集群,建立了topic test,用group ...
- django配置一个网站建设
第一步: 安装数据库MySQL,也可以使用pycharm自带的数据库sqllite,大项目要使用数据库.安装请参考上篇. 数据库在pycharm中驱动设置,setting文件中修改驱动文件密码等信息. ...
- Nginx详解四:Nginx基础篇之目录和配置语法
一.安装目录 命令:rpm -ql nginx 二.编译参数 命令:nginx -V 三.Nginx基本配置语法 修改主配置文件 当Nginx读配置文件读到include /etc/nginx/con ...