BZOJ 3504 [Cqoi2014] 危桥 最大流
来源:互联网 发布:mac 批量保存网页图片 编辑:程序博客网 时间:2024/04/20 03:20
题意:链接
方法:最大流
解析:这道题其实第一眼看上去是(和谐)题,然后发现水水的写完后WA了,然后从网上下来数据来观测数据,发现自己WA的地方都是同一个地方,之后上网上看了看其他人的姿势,算是懂了这道题吧。
首先读完题后,第一眼被这个往返卡了一会,后来发现,假如说从A到B,AB间是危桥的话,那你顶多在其中往返一次,也就是对应流量为1,如此的话,因为无向,所以B到A也必然有流量为1的一条路,在加上点细节修饰以及自己手画个图就能明白。
接下来我就以为这道题已经完事了,直接写了发最大流一跑发现WA了!
后经我亲测数据发现有的时候的流量并非自己所希望的从a1流向a2,有的满流的情况居然是从a1流到b2,这样怎么搞?
然后题解里给出了种办法,就是跑完第一次最大流后如果是满流则重新建图,其中桥的部分不变,源点到a1,a2到汇点的部分不变,只需要把原来的源点到b1,b2到汇点改为源点到b2,b1到汇点即可,再次判断,如果这样跑出来还是满流的话,就有解。
不过遗憾的是我并没有找到证明,所以就自己写了个证明,不知其严谨性。
第一次满流后
假设a1->a2 流量为 an-x
a1->b2 流量为 x
b1->a2 流量为 x
b1->b2 流量为 bn-x
之后我们假设第二次跑完之后又达到满流。
则a1->a2 流量仍为 an-x
∴a1->b1 流量为 x
b2->a2 流量为 x
b2->b1 流量为bn-x
又先前a1->b2 流量为x
∴a1->b2->b1流量为x(无向图)
则b2->b1又可有流量为x的一条路
又b2->b1已有流量为bn-x的一条路
∴b2->b1有流量为bn的一条路
则a1->a2有流量为an的一条路
得证
于是乎按照这个思路再跑一遍最大流就行了。
代码:
优于观测数据以及其他不可抗力原因,我的代码及其丑陋,所以他人的正常代码和我的解题思路更配哦- -
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 2700#define INF 0x3f3f3f3fusing namespace std;struct node { int to,val,next;}edge[N*N];int head[N],dep[N],map[N][N];int n,a1,a2,an,b1,b2,bn,cnt;char s[N];void init(){ memset(head,-1,sizeof(head));cnt=0;}void edgeadd(int from,int to,int val){ edge[cnt].to=to; edge[cnt].val=val; edge[cnt].next=head[from]; head[from]=cnt++;}int bfs(int s,int e){ memset(dep,0,sizeof(dep)); queue<int>q; q.push(s); dep[s]=1; while(!q.empty()) { int u=q.front(); if(u==e)return 1; q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int to=edge[i].to; if(edge[i].val==0||dep[to]!=0)continue; dep[to]=dep[u]+1; q.push(to); } } return 0;}int dfs(int s,int max_vale){ int ret=0,tmp; if(s==n*n+1)return max_vale; for(int i=head[s];i!=-1;i=edge[i].next) { int to=edge[i].to; if(edge[i].val==0||dep[to]!=dep[s]+1)continue; tmp=dfs(to,min(max_vale-ret,edge[i].val)); edge[i].val-=tmp; edge[i^1].val+=tmp; ret+=tmp; if(ret==max_vale)return ret; } return ret;}void build(){ init(); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(map[i][j]==1) { edgeadd(i,j,INF); edgeadd(j,i,0); }else if(map[i][j]==2) { edgeadd(i,j,1); edgeadd(j,i,0); } } }}int main(){// freopen("bridge.in","r",stdin);// freopen("bridge.out","w",stdout); while(~scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)) { memset(map,0,sizeof(map)); init(); a1++,a2++,b1++,b2++; for(int i=1;i<=n;i++) { scanf("%s",s); for(int j=0;j<n;j++) { if(s[j]=='N') { map[i][j+1]=1; }else if(s[j]=='O') { map[i][j+1]=2; } } } build(); edgeadd(0,a1,1*an); edgeadd(a1,0,0); edgeadd(a2,n*n+1,1*an); edgeadd(n*n+1,a2,0); edgeadd(0,b1,1*bn); edgeadd(b1,0,0); edgeadd(b2,n*n+1,1*bn); edgeadd(n*n+1,b2,0); int ret=0,flag=0; while(bfs(0,n*n+1)) { while(int t=dfs(0,INF)) { ret+=t; } } if(ret<1*(an+bn)){flag=1;} if(!flag) { build(); edgeadd(0,a1,1*an); edgeadd(a1,0,0); edgeadd(a2,n*n+1,1*an); edgeadd(n*n+1,a2,0); edgeadd(0,b2,1*bn); edgeadd(b2,0,0); edgeadd(b1,n*n+1,1*bn); edgeadd(n*n+1,b1,0); ret=0; while(bfs(0,n*n+1)) { while(int t=dfs(0,INF)) { ret+=t; } } if(ret<1*(an+bn)){flag=1;} } if(flag)printf("No\n"); else printf("Yes\n"); }}
1 0
- BZOJ 3504 [Cqoi2014] 危桥 最大流
- BZOJ 3504: [Cqoi2014]危桥 最大流
- bzoj 3504: [Cqoi2014]危桥(最大流)
- 3504: [Cqoi2014]危桥 最大流
- bzoj 3504 [Cqoi2014] 危桥
- 【bzoj 3504】: [Cqoi2014]危桥
- 【BZOJ 3504】 [Cqoi2014]危桥
- 【BZOJ 3504 】[Cqoi2014]危桥
- bzoj 3504: [Cqoi2014]危桥
- BZOJ 3504: [Cqoi2014]危桥
- BZOJ 3504: [Cqoi2014]危桥|网络流
- bzoj 3504: [Cqoi2014]危桥 网络流
- [BZOJ3504]CQOI2014危桥|最大流
- 【bzoj3504】[Cqoi2014]危桥 最大流
- 【bzoj3504】【cqoi2014】【危桥】【最大流】
- BZOJ P3504[Cqoi2014]危桥
- [BZOJ3504][CQOI2014]危桥(最大流)
- bzoj3504 [Cqoi2014]危桥(最大流)
- “贩卖儿童者,一律死刑!”可乎?
- 快速简单理解i2c标准协议
- Linux系统新手学习的11点建议
- 快速了解Android onMeasure() onLayout()
- eSDK UC极简开发敏捷创新系列之三: Huawei eSDK UC玩法进阶
- BZOJ 3504 [Cqoi2014] 危桥 最大流
- Bootstrap中的弹出框插件popover.js中的参数title、content不能使用html代码
- 北大OJ_1002题:487-3279
- C++基础概念
- 浙江大学PAT_甲级_1046. Shortest Distance (20)
- 讲讲Android开发超常见的内存泄露以及解决
- 解决AD 不能打开DDB文件的解决方案
- keepalived 实现mysql主从自动切换
- 倒计时