网络流|洛谷·[网络流24题]太空飞行计划问题

初见安~这里是传送门:洛谷P2762 太空飞行计划
【网络流|洛谷·[网络流24题]太空飞行计划问题】网络流|洛谷·[网络流24题]太空飞行计划问题
文章图片

Sol
这个题老鬼畜了……其实就是读入格式很恶心。
具体做法其实跑一个最大流就好了,明显是一个匹配问题。
直接贴代码吧【懒……但也是真的水。

#include #include #include #include #include #include #define maxn 500 #define maxm 200005 using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; bool flag; char ch; int read() { int x = 0, f = 1, ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * f; }struct edge {int to, w, nxt; } e[maxm]; int head[maxn], k = 0; void add(int u, int v, int w) { e[k] = {v, w, head[u]}; head[u] = k++; e[k] = {u, 0, head[v]}; head[v] = k++; }int d[maxn], S, T; queue q; bool bfs() { memset(d, 0, sizeof d); while(q.size()) q.pop(); q.push(S); d[S] = 1; while(q.size()) { register int u = q.front(), v; q.pop(); for(int i = head[u]; ~i; i = e[i].nxt) { v = e[i].to; if(e[i].w && !d[v]) { q.push(v), d[v] = d[u] + 1; if(v == T) return true; } } } return false; }int Dinic(int u, int flow) { if(u == T) return flow; register int rest = flow, k; for(int i = head[u], v; ~i && rest; i = e[i].nxt) { v = e[i].to; if(e[i].w && d[v] == d[u] + 1) { k = Dinic(v, min(rest, e[i].w)); if(!k) d[v] = 0; e[i].w -= k, e[i ^ 1].w += k; rest -= k; } } return flow - rest; }int n, m, sum = 0; signed main() { memset(head, -1, sizeof head); n = read(), m = read(); S = 0, T = n + m + 1; for(int i = 1, x; i <= n; i++) {//oh,这恶心的读入……而且你还需要看懂在干什么 x = read(); sum += x; add(S, i, x); //连边,只给x元保证不会亏 char tools[10000]; memset(tools,0,sizeof tools); cin.getline(tools,10000); int ulen=0,tool; while (sscanf(tools+ulen,"%d",&tool)==1) { add(i, tool + n, INF); //连边,匹配 if (tool==0) ulen++; else while (tool) { tool/=10; ulen++; } ulen++; } } for(int i = 1, x; i <= m; i++) x = read(), add(i + n, T, x); //连边,仪器开销。 register int flow, ans = 0; while(bfs()) while(flow = Dinic(S, INF)) ans += flow; //最大流保证每个实验的仪器开销一定满流,除非会亏 for(int i = 1; i <= n; i++) if(d[i]) printf("%d ", i); puts(""); for(int i = n + 1; i <= n + m; i++) if(d[i]) printf("%d ", i - n); //找匹配 printf("\n%d\n", sum - ans); return 0; }

咕咕咕了好久的一篇文章……
迎评:)
——End——

    推荐阅读