bzoj 3504(神题,网络流)

来源:互联网 发布:云杉网络 营收 编辑:程序博客网 时间:2024/06/05 12:52

3504: [Cqoi2014]危桥

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1165  Solved: 590
[Submit][Status][Discuss]

Description

Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双
向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?

Input


本题有多组测试数据。
每组数据第一行包含7个空格隔开的整数,分别为N、al、a2、an、bl、b2、bn。
接下来是一个N行N列的对称矩阵,由大写字母组成。矩阵的i行j列描述编号i一1和j-l的岛屿间的连接情况,若为“O”则表示有危桥相连:为“N”表示有普通的桥相连:为“X”表示没有桥相连。
|

Output

对于每组测试数据输出一行,如果他们都能完成愿望输出“Yes”,否则输出“No”。


Sample Input

4 0 1 1 2 3 1
XOXX
OXOX
XOXO
XXOX
4 0 2 1 1 3 2
XNXO
NXOX
XOXO
OXOX

Sample Output

Yes
No
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1

1 <=an. b<=50


解题思路:

神题。。。 网上证明好像有问题。。

就是先建图,跑最大流,看ans是否是2*an+2*bn。 

满足的话,将b1,b2交换再做,再判断,如果还满足就满足。


以后遇到这种题的话,实在不会证,就看看是否是满足对称性的,再考虑交换来做。


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define inf 0x7fffffff
#define ll long long
#define T 51
usingnamespacestd;
boolflag;
intn,a1,a2,an,b1,b2,bn;
intcnt,ans;
inth[55],q[55];
intmp[55][55];
structdata{intto,next,v;}e[100005];inthead[55],cur[55];
voidins(intu,intv,intw)
{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}
voidinsert(intu,intv,intw)
{ins(u,v,w);ins(v,u,0);}
voidbuild()
{
memset(head,0,sizeof(head));cnt=1;
for(inti=1;i<=n;i++)
    for(intj=1;j<=n;j++)
        if(mp[i][j]==1)insert(i,j,2);
        elseif(mp[i][j]==2)insert(i,j,inf);
}
boolbfs()
{
    intt=0,w=1;
    for(inti=0;i<=T;i++)h[i]=-1;
    q[0]=0;h[0]=0;
    while(t!=w)
    {
        intnow=q[t];t++;
        for(inti=head[now];i;i=e[i].next)
            if(e[i].v&&h[e[i].to]==-1)
            {
                h[e[i].to]=h[now]+1;
                q[w++]=e[i].to;
            }
    }
    if(h[T]==-1)return0;
    return1;
}
intdfs(intx,intf)
{
    if(x==T)returnf;
    intw,used=0;
    for(inti=cur[x];i;i=e[i].next)
    {
        if(e[i].v&&h[e[i].to]==h[x]+1)
        {
            w=f-used;
            w=dfs(e[i].to,min(e[i].v,w));
            e[i].v-=w;
            if(e[i].v)cur[x]=i;
            e[i^1].v+=w;
            used+=w;if(used==f)returnf;
        }
    }
    if(!used)h[x]=-1;
    returnused;
}
voiddinic()
{while(bfs()){for(inti=0;i<=T;i++)cur[i]=head[i];ans+=dfs(0,inf);}}
intmain()
{
while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF)
{
memset(mp,0,sizeof(mp));flag=0;
a1++;a2++;b1++;b2++;
for(inti=1;i<=n;i++)
{
charch[55];
scanf("%s",ch);
for(intj=1;j<=n;j++)
    if(ch[j-1]=='O')mp[i][j]=1;
    elseif(ch[j-1]=='N')mp[i][j]=2;
}
build();
insert(0,a1,an*2);insert(a2,T,an*2);
insert(0,b1,bn*2);insert(b2,T,bn*2);
ans=0;
dinic();
if(ans<2*(an+bn))flag=1;
if(!flag)
{
    build();
    insert(0,a1,an*2);insert(a2,T,an*2);
    insert(0,b2,bn*2);insert(b1,T,bn*2);
    ans=0;
    dinic();
    if(ans<2*(an+bn))flag=1;
}
if(flag)printf("No\n");
elseprintf("Yes\n");
}
return0;
}

0 0
原创粉丝点击