BZOJ 3504: [Cqoi2014]危桥 最大流

3504: [Cqoi2014]危桥

题目连接:

http://www.lydsy.com/JudgeOnline/problem.php?id=3504

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

题意

题解:

网络流

正常建边之后跑一遍网络流,但是这样可能会使得a1到an的流量跑到b1到bn去了,所以把b换过来

然后再跑一发网络流就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100000,MAXM=100000,inf=1e9;
struct Edge
{
    int v,c,f,nx;
    Edge() {}
    Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
} E[MAXM];
int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
void init(int _n)
{
    N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
}
void link(int u,int v,int c)
{
    E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
    E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
}
int ISAP(int S,int T)
{//S -> T
    int maxflow=0,aug=inf,flag=false,u,v;
    for (int i=0;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=0;
    for (gap[S]=N,u=pre[S]=S;dis[S]<N;flag=false)
    {
        for (int &it=cur[u];~it;it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
            {
                if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
                pre[v]=u,u=v; flag=true;
                if (u==T)
                {
                    for (maxflow+=aug;u!=S;)
                    {
                        E[cur[u=pre[u]]].f+=aug;
                        E[cur[u]^1].f-=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if (flag) continue;
        int mx=N;
        for (int it=G[u];~it;it=E[it].nx)
        {
            if (E[it].c>E[it].f&&dis[E[it].v]<mx)
            {
                mx=dis[E[it].v]; cur[u]=it;
            }
        }
        if ((--gap[dis[u]])==0) break;
        ++gap[dis[u]=mx+1]; u=pre[u];
    }
    return maxflow;
}
bool bfs(int S,int T)
{
    static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
    dis[S]=0; Q[0]=S;
    for (int h=0,t=1,u,v,it;h<t;++h)
    {
        for (u=Q[h],it=G[u];~it;it=E[it].nx)
        {
            if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
            {
                dis[v]=dis[u]+1; Q[t++]=v;
            }
        }
    }
    return dis[T]!=-1;
}
int dfs(int u,int T,int low)
{
    if (u==T) return low;
    int ret=0,tmp,v;
    for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
    {
        if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
        {
            if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
            {
                ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
            }
        }
    }
    if (!ret) dis[u]=-1; return ret;
}
int dinic(int S,int T)
{
    int maxflow=0,tmp;
    while (bfs(S,T))
    {
        memcpy(cur,G,sizeof(G[0])*N);
        while (tmp=dfs(S,T,inf)) maxflow+=tmp;
    }
    return maxflow;
}
int n,a1,a2,an,b1,b2,bn,flag;
char s[55][55];
void build()
{
    init(100000);
    int S=n*n+1,T=n*n+2;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            if(s[i][j]=='O')link(i,j,2);
            else if(s[i][j]=='N')link(i,j,inf);
    link(S,a1,an*2);
    link(S,b1,bn*2);
    link(a2,T,an*2);
    link(b2,T,bn*2);
    if(dinic(S,T)!=2*an+2*bn)flag=1;
}
int main()
{
    while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF){
        flag=0;
        for(int i=0;i<n;i++)scanf("%s",s[i]);
        build();
        swap(b1,b2);
        build();
        if(flag)printf("No\n");
        else printf("Yes\n");
    }
}

你可能感兴趣的:(BZOJ 3504: [Cqoi2014]危桥 最大流)