解题思路
考虑如何建模。
既然是网络流,那么肯定要有源点和汇点。而这个题目并没有什么明显的源点和汇点。
想一想,如果一个飞机能够起飞的话,那么必定有一对可以配对的正副驾驶员。也就是说一条曾广路能够上必定有且只有一对配对的管理员。
这里引入一个超级源点和超级汇点。超级源点就和正驾驶相连,流量为$1$。副驾驶员和汇点相连。模型就建好了。
之后就是跑$Dinic$,网络流模板不难,难的是建模QAQ
附上代码
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int maxnode = 105, maxedge = 30003, INF = 2147483647; int n, m, s, t, head[maxnode], cnt = 1, Depth[maxnode], Ans; struct Edge { int nxt, v, w; }ed[maxedge]; inline void addedge(int u, int v, int w) { ed[++cnt].nxt = head[u]; ed[cnt].v = v, ed[cnt].w = w; head[u] = cnt; } inline bool BFS() { queue <int> Q; memset(Depth, 0, sizeof(Depth)); Depth[s] = 1, Q.push(s); int u; while (!Q.empty()) { u = Q.front(); Q.pop(); for(int i=head[u]; i; i=ed[i].nxt) { if(Depth[ed[i].v] == 0 && ed[i].w > 0) { Depth[ed[i].v] = Depth[u] + 1; Q.push(ed[i].v); if(ed[i].v == t) return true; } } } return false; } inline int Dinic(int u, int cap) { if(u == t) return cap; int delta; for(int i=head[u]; i; i=ed[i].nxt) { if(ed[i].w > 0 && Depth[ed[i].v] == Depth[u] + 1) { delta = Dinic(ed[i].v, min(cap, ed[i].w)); if(delta > 0) { ed[i].w -= delta; ed[i^1].w += delta; return delta; } } } return 0; } int main() { scanf("%d%d", &n, &m); s = 0, t = n+1; for(int i=1; i<=m; i++) addedge(s, i, 1), addedge(i, s, 0); for(int i=m+1; i<=n; i++) addedge(i, t, 1), addedge(t, i, 0); static int x, y; while (scanf("%d%d", &x, &y) == 2) addedge(x, y, 1), addedge(y, x, 0); while (BFS()) Ans += Dinic(s, INF); printf("%d", Ans); }