3504: [Cqoi2014]危桥
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 946 Solved: 497
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
自己YY了一下建模没想出来,于是参考了一下黄学长的建模方式。。
然而编完发现无端RE无数次。。
感谢Shallwe&DaD3zZ神犇。。
改输出。。
改数组大小。。
终于AC。。
说一下建模思路:
首先源点为0,汇点为60,其实50以上都可以。。
先a1和源点连边,a2和汇点连边,因为一个桥Alice希望往返,容量为2*an。。
Bob同理。。
对于字符矩阵,危桥容量为2,完好的桥容量无穷大。。
但是只做一遍会有问题:比如从a1万一到不了a2,然而最终流到了b2,这样显然是不可行的。那么我们可以把b1和b2反一下再做一遍,如果还是满流就可以了。。
附上本蒟蒻的代码:
#include
#include
#include
#include
using namespace std;
#define T 60
#define inf 0x7fffffff
int n,f[T][T],q[1000000],h[1000000],dis[1000000],head,tail,cnt=1,ans,sum=0,cur[1000000];
struct node
{
int to,next,v;
};
node edge[1000000];
void add(int u,int v,int w)
{
cnt++;
edge[cnt].next=h[u];
h[u]=cnt;
edge[cnt].to=v;
edge[cnt].v=w;
cnt++;
edge[cnt].next=h[v];
h[v]=cnt;
edge[cnt].to=u;
edge[cnt].v=0;
}
bool bfs()
{
int j,p;
memset(dis,-1,sizeof(dis));
head=0;
tail=1;
q[0]=0;
dis[0]=0;
while (headq[head];
p=h[j];
while (p)
{
if (dis[edge[p].to]<0 && edge[p].v>0)
{
dis[edge[p].to]=dis[j]+1;
tail++;
q[tail]=edge[p].to;
}
p=edge[p].next;
}
}
if (dis[T]>0)
return true;
else
return false;
}
int dfs(int x,int f)
{
int w,used=0,i=h[x];
if (x==T)
return f;
while (i)
{
if (edge[i].v && dis[edge[i].to]==dis[x]+1)
{
w=f-used;
w=dfs(edge[i].to,min(w,edge[i].v));
edge[i].v-=w;
edge[i^1].v+=w;
used+=w;
if (used==f)
return f;
}
i=edge[i].next;
}
if (!used)
dis[x]=-1;
return used;
}
void build()
{
int i,j;
memset(h,0,sizeof(h));
cnt=1;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
if (f[i][j]==1)
add(i,j,inf);
if (f[i][j]==2)
add(i,j,2);
}
}
int main()
{
int a1,a2,b1,b2,an,bn,i,j;
char c[51];
bool flag;
while ((scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn))!=EOF)
{
a1++;
a2++;
b1++;
b2++;
memset(f,0,sizeof(f));
flag=false;
for (i=1;i<=n;i++)
{
scanf("%s",&c);
for (j=1;j<=n;j++)
{
if (c[j-1]=='O')
f[i][j]=2;
if (c[j-1]=='N')
f[i][j]=1;
}
}
build();
add(0,a1,2*an);
add(a2,T,2*an);
add(0,b1,2*bn);
add(b2,T,2*bn);
ans=0;
while (bfs())
while (sum=dfs(0,inf))
ans+=sum;
if (ans<2*(an+bn))
flag=true;
if (!flag)
{
build();
add(0,a1,2*an);
add(a2,T,2*an);
add(0,b2,2*bn);
add(b1,T,2*bn);
ans=0;
for (i=0;i<=T;i++)
cur[i]=h[i];
while (bfs())
while (sum=dfs(0,inf))
ans+=sum;
if (ans<2*(an+bn))
flag=true;
}
if (!flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}