LOJ#2239. 「CQOI2014」危桥
就是先把每条边正着连一条容量为2的边,反着连一条容量为2的边
显然如果只有一个人走的话,答案就是一个源点往起点连一条容量为次数×2的边,终点往汇点连一个次数×2的边,跑最大流看是否满流即可
两个人的话由于两个人的路径可能相交,有可能从\(a_1\)走到了\(b_2\)
统计一遍 \(a_1,b_{1}\)为源点,\(a_{2},b_{2}\)为汇点的情况
再统计一遍\(a_{1},b_{2}\)为源点,\(a_{2},b_{1}\)为汇点的情况
这两种都合法的话才能证明可以走到
#include#define fi first#define se second#define pii pair #define mp make_pair#define pb push_back#define space putchar(' ')#define enter putchar('\n')#define eps 1e-10#define ba 47#define MAXN 1005//#define ivorysiusing namespace std;typedef long long int64;typedef unsigned int u32;typedef double db;template void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f;}template void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10);}int N;int a[3],b[3];int S,T,dis[55];char g[55][55];struct node { int to,next,cap;}E[100005];int head[55],sumE = 1;void add(int u,int v,int c) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].cap = c; head[u] = sumE;}void addtwo(int u,int v,int c) { add(u,v,c);add(v,u,0);}queue Q;bool BFS() { Q.push(S); memset(dis,0,sizeof(dis)); dis[S] = 1; while(!Q.empty()) Q.pop(); Q.push(S); while(!Q.empty()) { int u = Q.front();Q.pop(); if(u == T) return true; for(int i = head[u] ; i; i = E[i].next) { int v = E[i].to; if(E[i].cap > 0 && !dis[v]) { dis[v] = dis[u] + 1; if(v == T) return true; Q.push(v); } } } return dis[T] != 0;}int dfs(int u,int aug) { if(u == T) return aug; int flow = 0; for(int i = head[u] ; i; i = E[i].next) { int v = E[i].to; if(dis[v] == dis[u] + 1) { int t = dfs(v,min(aug - flow,E[i].cap)); flow += t; E[i].cap -= t; E[i ^ 1].cap += t; if(flow == aug) return flow; } } return flow;}int Dinic() { int res = 0; while(BFS()) { while(int d = dfs(S,1e9)) { res += d; } } return res;}void create() { sumE = 1;memset(head,0,sizeof(head)); for(int i = 1 ; i <= N ; ++i) { for(int j = 1 ; j <= N ; ++j) { if(g[i][j] == 'N') addtwo(i,j,1e9); else if(g[i][j] == 'O') addtwo(i,j,2); } }}bool Process() { create(); addtwo(S,a[0],2 * a[2]); addtwo(S,b[0],2 * b[2]); addtwo(a[1],T,2 * a[2]); addtwo(b[1],T,2 * b[2]); return Dinic() >= 2 * (a[2] + b[2]);}void Solve() { for(int i = 0 ; i < 3 ; ++i) read(a[i]); ++a[0];++a[1]; for(int i = 0 ; i < 3 ; ++i) read(b[i]); ++b[0];++b[1]; for(int i = 1 ; i <= N ; ++i) scanf("%s",g[i] + 1); S = N + 1;T = N + 2; bool f = 1; f &= Process(); swap(b[0],b[1]); f &= Process(); if(f) puts("Yes"); else puts("No");}int main(){#ifdef ivorysi freopen("f1.in","r",stdin);#endif while(scanf("%d",&N) != EOF) { Solve(); }}