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+requests库框架设计06-测试脚本
在项目下新建TestCase文件夹,然后新建.py文件在文件中写关于接口具体的测试脚本,一般我喜欢按照模块来分,一个模块一个.py文件,建议以test开头命名文件 把配置文件改成这样 url:http ...
- 微信小程序开发记录
顶栏banner代码 /**app.wxss**/ .container { height: 100%; display: flex; flex-direction: column; align-it ...
- VS2013中如何解决error C4996: 'fopen'问题
今天编写控制台应用程序时出现如下错误 error C4996: 'fopen': This function or variable may be unsafe. Consider using fop ...
- 026_lsof命令经验总结
一.lsof处理删除文件未释放句柄问题. 但是如果你不知道是哪个文件,或者是很多文件都有这样的情况,那你需要使用如下命令 lsof |grep deleted 注:这个deleted表示该已经删除了的 ...
- xl2tpd[26104]: Maximum retries exceeded for tunnel 33925. Closing
Sep 5 14:31:50 root charon: 13[ENC] generating QUICK_MODE request 3930082374 [ HASH ]Sep 5 14:31:5 ...
- Windows系统下安装dig命令
dig 是一个 Linux 下用来 DNS 查询信息的工具,全称是Domain Information Groper,与 nslookup 类似,但比 nslookup 功能更强大.Windows 下 ...
- (转)dubbo远程调用细节
作者: 白文志 (来自开源社区) 服务提供者暴露一个服务的详细过程 上图是服务提供者暴露服务的主过程:首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl) ...
- JavaScript 删除某个数组中指定的对象
返回对象在数组中的下标: _arr表示一个Array数组,里面包括了很多的对象如下图: _obj表示某一个数组对象 function getIndex (_arr,_obj) { var le ...
- 机器学习之线性回归---logistic回归---softmax回归
在本节中,我们介绍Softmax回归模型,该模型是logistic回归模型在多分类问题上的推广,在多分类问题中,类标签 可以取两个以上的值. Softmax回归模型对于诸如MNIST手写数字分类等问题 ...
- Confluence 6 通过 SSL 或 HTTPS 运行 - 备注和问题解决
备注 在创建证书时候的背景信息: 'keytool -genkeypair' 命令将会创建秘钥对,包括公钥和关联的私钥,然后存储到 keystore 中.这个命令打包公钥为 X.509 v3 自签 ...