bzoj3504[Cqoi2014]危桥

bzoj3504[Cqoi2014]危桥

题意:

有N座岛屿,某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥是危桥。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2 到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。判断两人能否达成愿望。

题解:

网络流,每天边的容量就是这条边可以走几次,建一个超级源连a1b1,a2b2连超级汇,如果最大流大于等于2*(b1+b2)就行。但有可能出现a1流到b2导致原来的不可行被判断成可行,这样我们就需要把b2和b1调换位置,如果结果一样,说明这个方案是真正可行的,具体原因我还不懂,好像是如果两个结果一样,即使真的出现了a1流到b2的情况,也能通过调整变成正确的流动方案,蒟蒻太弱了!

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #define INF 0x3fffffff
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 using namespace std;
 8 
 9 struct e{int t,c,n;}; e es[10000]; int ess,g[100];
10 void pe(int f,int t,int c){es[++ess]=(e){t,c,g[f]}; g[f]=ess; es[++ess]=(e){f,0,g[t]}; g[t]=ess;}
11 char map[100][100]; int n,a1,a2,an,b1,b2,bn,s,t;
12 queue <int> q; int h[100];
13 bool bfs(int s,int t){
14     while(! q.empty())q.pop(); memset(h,-1,sizeof(h)); h[s]=0; q.push(s);
15     while(! q.empty()){
16         int x=q.front(); q.pop();
17         for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==-1)h[es[i].t]=h[x]+1,q.push(es[i].t);
18     }
19     if(h[t]==-1)return 0;else return 1;
20 }
21 int dfs(int x,int t,int f){
22     if(x==t)return f; int u=0;
23     for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==h[x]+1){
24         int w=dfs(es[i].t,t,min(f,es[i].c)); es[i].c-=w; es[i^1].c+=w; f-=w; u+=w;
25         if(f==0)return u;
26     }
27     if(u==0)h[x]=-1; return u;
28 }
29 int dinic(int s,int t){int f=0; while(bfs(s,t))f+=dfs(s,t,INF); return f;}
30 int main(){
31     while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF){
32         inc(i,1,n)scanf("%s",map[i]); a1++; a2++; b1++; b2++; s=0; t=n+1;
33         ess=-1; memset(g,-1,sizeof(g)); pe(s,a1,2*an); pe(s,b1,2*bn); pe(a2,t,2*an); pe(b2,t,2*bn);
34         inc(i,1,n)inc(j,0,n-1){
35             if(map[i][j]=='O')pe(i,j+1,2);
36             if(map[i][j]=='N')pe(i,j+1,INF);
37         }
38         if(dinic(s,t)>=2*an+2*bn){
39             ess=-1; memset(g,-1,sizeof(g)); pe(s,a1,2*an); pe(s,b2,2*bn); pe(a2,t,2*an); pe(b1,t,2*bn);
40             inc(i,1,n)inc(j,0,n-1){
41                 if(map[i][j]=='O')pe(i,j+1,2);
42                 if(map[i][j]=='N')pe(i,j+1,INF);
43             }
44             if(dinic(s,t)>=2*an+2*bn)printf("Yes\n");else printf("No\n");
45         }else printf("No\n");
46     }
47     return 0;
48 }

 

20160408

转载于:https://www.cnblogs.com/YuanZiming/p/5697031.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值