bzoj 3504: [Cqoi2014]危桥

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[N],next[M*2],remain[M*2];
int v[M*2],a[300][300],maxflow,tot,last[N],deep[N],cur[N],num[N];
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");
	}
}




你可能感兴趣的:(bzoj 3504: [Cqoi2014]危桥)