bzoj3504 [Cqoi2014]危桥 (网络流 最大流)
2017-12-06 21:12
357 查看
bzoj3504: [Cqoi2014]危桥
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3504题意:
Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1
1 <=an. b<=50
题解:
很容易想到网络流,最容易想的建边方式是:
危桥:双向各一条容量为1的边(当然还各有反边,共四条边)
普通桥:双向各一条容量为inf的边
S到a1给an的流量,S到b1给bn的流量,a2->T,b2->T,看是否满流。
但是这样有两个问题:
1、b1与a2相通,那么b1的流入就可以不通过b2到达T,而是通过走a2到达T。
2、同一个危桥,a1->a2与b1->b2走这座桥是不同方向的,而正反流量都是1,那么两次往返都可能会走到这座桥,就是4次,但不会被判出来。
而解决这些问题的办法:
交换b1,b2再跑一次。
即,把S连向b2,b1连向T再跑一次。要两次都合法才算合法。
方向变了解决了问题二,而对于问题一:
如果 b2仍然可以”绕路”,那么b1,b2都可绕到a2的路相连就成了一条路,
因此两次都合法就合法了
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #define LL long long using namespace std; queue<int> Q; const int N=55; const int inf=10000; int S,T,n,head ,to[4*N*N],nxt[4*N*N],w[4*N*N],a1,a2,an,b1,b2,bn,num,dep ; bool vis ; char s ; void build(int u,int v,int ww) { num++; to[num]=v; nxt[num]=head[u]; w[num]=ww; head[u]=num; num++; to[num]=u; nxt[num]=head[v]; w[num]=0; head[v]=num; } void init(int opt) { memset(head,0,sizeof(head)); num=1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(s[i][j]=='O') build(i,j,1); else if(s[i][j]=='N') build(i,j,inf); } } build(S,a1,an);build(a2,T,inf); if(opt==1) {build(S,b1,bn); build(b2,T,inf);} else {build(S,b2,bn); build(b1,T,inf);} } bool bfs() { while(!Q.empty()) Q.pop(); memset(vis,0,sizeof(vis)); memset(dep,0,sizeof(dep)); vis[S]=1; dep[S]=1; Q.push(S); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(vis[v]||w[i]<=0) continue; dep[v]=dep[u]+1; vis[v]=1; Q.push(v); } } return vis[T]; } int dfs(int u,int d) { if(!d||u==T) return d; int ret=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(dep[v]!=dep[u]+1||w[i]<=0) continue; int flow=dfs(v,min(d,w[i])); ret+=flow; d-=flow; w[i]-=flow; w[i^1]+=flow; } if(ret==0) dep[u]=-1; return ret; } bool check() { int ret=0; while(bfs()) { ret+=dfs(S,inf); } return ret>=an+bn; } int main() { while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF) { a1++; a2++; b1++;b2++; S=n+1; T=n+2; for(int i=1;i<=n;i++) scanf("%s",s[i]+1); bool flag=1; for(int opt=1;opt<=2;opt++) { init(opt); if(!check()) flag=0; } if(!flag) printf("No\n"); else printf("Yes\n"); } return 0; }
相关文章推荐
- [BZOJ3504][CQOI2014]危桥(网络流)
- BZOJ 3504: [Cqoi2014]危桥 最大流
- BZOJ 3504: [Cqoi2014]危桥 最大流
- bzoj 3504: [Cqoi2014]危桥(最大流)
- bzoj 3504: [Cqoi2014]危桥 网络流
- BZOJ 3504 CQOI 2014 危桥 最大流
- 【bzoj3504】[Cqoi2014]危桥 网络流
- BZOJ 3504: [Cqoi2014]危桥|网络流
- 【bzoj3504】【cqoi2014】【危桥】【最大流】
- bzoj3504 [Cqoi2014]危桥(最大流)
- [BZOJ3504][CQOI2014]危桥(最大流)
- [BZOJ3504] [Cqoi2014]危桥(网络流)
- [BZOJ3504][CQOI2014]危桥(最大流)
- BZOJ 3504: [Cqoi2014]危桥 [最大流]
- BZOJ 3504 [Cqoi2014] 危桥 最大流
- BZOJ3504 CQOI2014危桥(最大流)
- bzoj 3504: [Cqoi2014]危桥【最大流】
- 【bzoj3504】[Cqoi2014]危桥 最大流
- [BZOJ3504]CQOI2014危桥|最大流
- [CQOI2014][bzoj3504] 危桥 [最大流]