• [CQOI2014]危桥


    题目描述

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

    题解

    有一个初步的想法,因为图是无向的,所以我们的往返可以看做走两遍。

    所以我们就把无向图连出来,然后连上源和汇跑一遍最大流,然后检查是否漫流。

    但这样会有一个问题,两股流有可能会有交叉的地方,这样我们有可能会把无解判断成有解。

    也就是(s1->t2 s2->t1)

    正解非常巧妙,就是把一条路径反过来再跑一遍,如果还漫流,则说明有解。

    为什么,这时如果还满流,那么会有(s1->s2 t2->t1)那么这说明(s1)是这股流是可以到(t1)的,(s2)也是可以到(t2)的,则它是有解的。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define N 60
    #define inf 1e9
    using namespace std;
    queue<int>q;
    int head[N],tot=1,cur[N],deep[N],n,ans;
    char s[N][N];
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{
    	int n,to,l;
    }e[N*N*10];
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
        e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
    }
    bool bfs(int s,int t){
        memcpy(cur,head,sizeof(head));
        memset(deep,0,sizeof(deep));
        q.push(s);deep[s]=1;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(!deep[v]&&e[i].l){
                    deep[v]=deep[u]+1;
                    q.push(v);
                }
            }
        }
        return deep[t];
    }
    int dfs(int u,int t,int l){
        if(u==t||!l)return l;
        int flow=0,f;
        for(int &i=cur[u];i;i=e[i].n){
          int v=e[i].to;
          if(deep[v]==deep[u]+1&&(f=dfs(v,t,min(l,e[i].l)))){
          	  e[i].l-=f;e[i^1].l+=f;flow+=f;l-=f;
          	  if(!l)break;
          }
        }
        return flow;
    }
    int main(){
    	int a1,a2,an,b1,b2,bn;
    	while(scanf("%d",&n)!=EOF){
    		a1=rd()+1;a2=rd()+1;an=rd();b1=rd()+1;b2=rd()+1;bn=rd();;
    		for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
    		tot=1;
    		memset(head,0,sizeof(head));
    		for(int i=1;i<=n;++i)
    		  for(int j=1;j<i;++j)
    		    if(s[i][j]=='N')add(i,j,inf);
    		    else if(s[i][j]=='O')add(i,j,1);
    		add(0,a1,an);add(0,b1,bn);
    		add(a2,n+1,an);add(b2,n+1,bn);ans=0;
    		while(bfs(0,n+1))ans+=dfs(0,n+1,inf);
    		if(ans!=an+bn){puts("No");continue;}
    		tot=1;
    		memset(head,0,sizeof(head));
    		for(int i=1;i<=n;++i)
    		  for(int j=1;j<i;++j)
    		    if(s[i][j]=='N')add(i,j,inf);
    		    else if(s[i][j]=='O')add(i,j,1);
    		add(0,a1,an);add(0,b2,bn);
    		add(a2,n+1,an);add(b1,n+1,bn);ans=0;
    		while(bfs(0,n+1))ans+=dfs(0,n+1,inf);
    		if(ans!=an+bn){puts("No");continue;}
    		puts("Yes");
    	}
    	return 0;
    }
    
  • 相关阅读:
    OpenCV_Python —— (6)图像色彩空间
    OpenCV_Python —— (5)图像模糊/平滑/滤波
    Java 14 祭出增强版 switch,真香!!
    推荐 9 个 爱不释手的 JSON 工具!
    从 0 开始手写一个 Mybatis 框架,三步搞定!
    Java常用的几个Json库,性能强势对比!
    Oracle JDK 和 OpenJDK 有什么区别?
    极客时间-左耳听风-程序员攻略-UI/UX设计
    OpenCV导向滤波(引导滤波)实现(Guided Filter)代码,以及使用颜色先验算法去雾
    python面向对象小练习
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10562668.html
Copyright © 2020-2023  润新知