网络流练习
NC19931 危桥
#include <bits/stdc++.h> using namespace std; const int maxn = 55; const int INF = 0x3f3f3f3f; struct edge { int to, cap, rev; //rev记录对应反向边在对应邻接表的下标 edge(int k1, int k2, int k3): to{k1}, cap{k2}, rev{k3} {} }; struct flow { vector<edge> G[maxn]; int level[maxn], iter[maxn]; //level记录bfs时与s的距离,iter记录当前弧 void add_edge(int from, int to, int cap) { //cout << from << ' ' << to << ' ' << cap << endl; G[from].push_back((edge){to, cap, (int)G[to].size()}); G[to].push_back((edge){from, 0, (int)G[from].size()-1}); } void bfs(int s, int t) { queue<int> que; memset(level, -1, sizeof(level)); level[s] = 0; que.push(s); while(!que.empty()) { int v = que.front(); que.pop(); for(int i = 0; i < G[v].size(); i++) { edge &e = G[v][i]; if(e.cap > 0 && level[e.to] < 0) //其可达并且第一次到达 { level[e.to] = level[v] + 1; if(e.to == t) return; que.push(e.to); } } } } int dfs(int v, int t, int f) //从v到t的最大流 { if(v == t) return f; for(int &i = iter[v]; i < G[v].size(); i++) //弧优化 { edge &e = G[v][i]; if(e.cap > 0 && level[v] < level[e.to]) //可达并且是下一层 { int d = dfs(e.to, t, min(f, e.cap)); if(d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0; } int max_flow(int s, int t) { int flow = 0, f; for(;;) { bfs(s, t); //首先bfs构造分层图 if(level[t] < 0) return flow; //t不可达直接退出 memset(iter, 0, sizeof(iter)); while((f = dfs(s, t, INF)) > 0) //每次增加一条最短增广路 flow += f; } } }f, g; int main() { int n, a1, a2, an, b1, b2, bn; char c; while(scanf("%d %d %d %d %d %d %d", &n, &a1, &a2, &an, &b1, &b2, &bn) == 7) { for(int i = 0; i < maxn; ++i) f.G[i].clear(); memset(f.level, 0, sizeof(f.level)); memset(f.iter, 0, sizeof(f.iter)); for(int i = 0; i < maxn; ++i) g.G[i].clear(); memset(g.level, 0, sizeof(g.level)); memset(g.iter, 0, sizeof(g.iter)); for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) { scanf(" %c", &c); if(c == 'N') f.add_edge(i, j, INF); else if(c == 'O') f.add_edge(i, j, 2); } g = f; int s = n, t = n + 1; f.add_edge(s, a1, 2 * an), f.add_edge(s, b1, 2 * bn); f.add_edge(a2, t, 2 * an), f.add_edge(b2, t, 2 * bn); g.add_edge(s, a1, 2 * an), g.add_edge(s, b2, 2 * bn); g.add_edge(a2, t, 2 * an), g.add_edge(b1, t, 2 * bn); if(f.max_flow(s, t) == 2 * an + 2 * bn && g.max_flow(s, t) == 2 * an + 2 * bn) printf("Yes\n"); else printf("No\n"); } }