P3163 [CQOI2014]危桥

传送门

我是看不出这玩意儿和网络流有什么关系……
我们把图中的所有边都当成无向边加入图中,容量为(inf)
危桥的容量为(2)
从源点到(a1,b1)连边容量为(an*2)(a2,b2)到汇点连边容量(bn*2),相当于一次把两边都走完
然后跑一遍看看是否满流即可
然而这样会有一个问题,就是最终求得的最大流是(a1)流向(b2)(a2)流向(b1)
于是再从源点向(a1)(b2)连边,(a2)(b1)向汇点连边,再跑一遍看看是否满流就是了

//minamoto
#include<bits/stdc++.h>
#define R register
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(R int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define gg(u) for(int &i=cur[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
inline int min(const R int &x,const R int &y){return x<y?x:y;}
using namespace std;
const int N=105,M=N*N*2;
struct eg{int v,nx,w;}e[M];int head[N],tot=1;
inline void add(R int u,R int v,R int w){
    e[++tot]={v,head[u],w},head[u]=tot;
    e[++tot]={u,head[v],w},head[v]=tot;
}
int dep[N],q[N],cur[N],S,T,h,t,u;
bool bfs(){
    fp(i,S,T)cur[i]=head[i],dep[i]=-1;
    q[h=t=1]=S,dep[S]=0;
    while(h<=t){
        int u=q[h++];
        go(u)if(e[i].w&&dep[v]<0){
            dep[v]=dep[u]+1,q[++t]=v;
            if(v==T)return true;
        }
    }return false;
}
int dfs(int u,int lim){
    if(u==T||!lim)return lim;
    int flow=0,f;
    gg(u)if(dep[v]==dep[u]+1&&(f=dfs(v,min(lim,e[i].w)))){
        flow+=f,lim-=f;
        e[i].w-=f,e[i^1].w+=f;
        if(!lim)break;
    }return flow;
}
int dinic(){int flow=0;while(bfs())flow+=dfs(S,inf);return flow;}
int n,m,a1,a2,an,b1,b2,bn;char s[N];int mmp[N][N];
inline void clr(){tot=1;memset(head,0,sizeof(head));}
void solve(){
    clr();fp(i,1,n){
        scanf("%s",s+1);
        fp(j,1,n)mmp[i][j]=s[j]!='X'?s[j]!='N'?2:1:0;
    }
    fp(i,1,n)fp(j,i+1,n)if(mmp[i][j])add(i,j,mmp[i][j]==2?2:inf);
    S=0,T=n+1,++a1,++b1,++a2,++b2;
    add(S,a1,an<<1),add(S,b1,bn<<1),add(a2,T,an<<1),add(b2,T,bn<<1);
//	printf("%d
",dinic());
    if(dinic()!=2*an+2*bn)return (void)(puts("No"));
    clr();fp(i,1,n)fp(j,i+1,n)if(mmp[i][j])add(i,j,mmp[i][j]==2?2:inf);
    add(S,a1,an<<1),add(S,b2,bn<<1),add(a2,T,an<<1),add(b1,T,bn<<1);
//	printf("%d
",dinic());
    if(dinic()!=(2*an+2*bn))return (void)(puts("No"));
    puts("Yes");
}
int main(){
//	freopen("testdata.in","r",stdin);
    while(~scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn))solve();
    return 0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10078058.html