P1343 地震逃生(网络流入门)
题目大意:学生们同时逃生,有多条路径选择,路径容量有限,一批一批逃生,问最少需要多少批才能逃生完成。
思路:最大流入门题,都根本不需要考虑如何建图,提单第一题,顺利过关。
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 100005; const int inf = 0x3f3f3f3f; struct edge { int f, t, nxt; ll flow; }e[maxn]; int hd[maxn], tot=1; void add(int f, int t,ll flow) { e[++tot] = { f,t,hd[f],flow }; hd[f] = tot; } int n, m, x; int s, d; int dep[maxn], cur[maxn]; bool bfs() {//找增广路 memset(dep, 0, sizeof(dep)); dep[s] = 1; queue<int>Q; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t, flow = e[i].flow; if (flow > 0 && !dep[v]) { dep[v] = dep[u] + 1; if (v == d)return true; Q.push(v); } } } return false; } ll dfs(int u, ll flow) { if (u == d)return flow; ll last = flow; for (int i = cur[u]; i; i = e[i].nxt) { cur[u] = i;//当前弧优化 int v = e[i].t;ll flow = e[i].flow; if (flow > 0 && dep[v] == dep[u] + 1) { ll tmp = dfs(v, min(last, flow)); last -= tmp; e[i].flow -= tmp; e[i ^ 1].flow += tmp; if (last == 0)break;//流量没了直接退出循环,与当前弧优化对应 } } if (last == flow)dep[u] = 0;//从当前点一点流量没流到终点(未找到增广路),炸点优化 return flow - last;//返回剩余流量 } ll dinic() { ll maxflow = 0; while (bfs()) { memcpy(cur, hd, sizeof(hd)); maxflow += dfs(s, inf); } return maxflow; } int main() { //freopen("test.txt", "r", stdin); scanf("%d%d%d", &n, &m, &x); for (int i = 1; i <= m; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b, c); add(b, a, 0); } s = n + 1, d = n + 2; add(s, 1, inf); add(n, d, inf); ll ans = dinic(); if (!ans) { printf("Orz Ni Jinan Saint Cow!\n"); }else printf("%lld %lld\n", ans, (x + ans-1) / ans); return 0; }