您的位置:首页 > 其它

bzoj 3504: [Cqoi2014]危桥

2016-04-07 21:20 246 查看

3504: [Cqoi2014]危桥

Time Limit: 10 Sec Memory Limit: 128 MB

Submit: 1145 Solved: 578

[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

HINT

Source

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 10000
#define M 200000
using namespace std;
int m,n,a1,a2,an,b1,b2,bn;
int point
,next[M*2],remain[M*2];
int v[M*2],a[300][300],maxflow,tot,last
,deep
,cur
,num
;
const int inf=1e9;
void clear()
{
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
memset(num,0,sizeof(num));
}
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
void build()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]) add(1+i,1+j,a[i][j]);
}
int addflow(int s,int t)
{
int now=t; int ans=inf;
while(now!=s)
{
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while(now!=s)
{
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
void bfs(int s,int t)
{
for (int i=s;i<=t;i++) deep[i]=t;
deep[t]=0;
queue<int> p; p.push(t);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]==t&&remain[i^1])
deep[v[i]]=deep[now]+1,p.push(v[i]);
}
}
void isap(int s,int t)
{
maxflow=0;
bfs(s,t);
for (int i=s;i<=t;i++) cur[i]=point[i];
for (int i=s;i<=t;i++) num[deep[i]]++;
int now=s;
while (deep[s]<t)
{
if (now==t)
{
maxflow+=addflow(s,t);
now=s;
}
int p=false;
for (int i=cur[now];i!=-1;i=next[i])
if (deep[v[i]]+1==deep[now]&&remain[i])
{
cur[now]=i;
p=true;
last[v[i]]=i;
now=v[i];
break;
}
if (!p)
{
int minn=t-1;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!--num[deep[now]]) break;
deep[now]=minn+1;
num[deep[now]]++;
cur[now]=point[now];
if (now!=s)
now=v[last[now]^1];

}
}
}
int main()
{
while (~scanf("%d",&n))
{
scanf("%d%d%d%d%d%d",&a1,&a2,&an,&b1,&b2,&bn);
a1++;  a2++; b1++; b2++;
for (int i=1;i<=n;i++)
{
char s[100]; scanf("%s",s);
for (int j=0;j<n;j++)
{
if (s[j]=='X')a[i][j+1]=0;
if (s[j]=='N')a[i][j+1]=inf;
if (s[j]=='O')a[i][j+1]=2;
}
}
clear();
build();
add(1,a1+1,2*an); add(a2+1,n+2,2*an);
add(1,b1+1,2*bn); add(b2+1,n+2,2*bn);
isap(1,n+2);
//cout<<maxflow<<endl;
if (maxflow<2*(an+bn))
{
printf("No\n");
continue;
}
clear();
build();
add(1,a1+1,2*an); add(a2+1,n+2,2*an);
add(1,b2+1,2*bn); add(b1+1,n+2,2*bn);
isap(1,n+2);
if (maxflow<2*(an+bn))
{
printf("No\n");
continue;
}
else printf("Yes\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: