星际转移问题(最大流 枚举)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了星际转移问题(最大流 枚举)相关的知识,希望对你有一定的参考价值。
使用并查集判断有无解,若有解枚举天数若最大流等于人数则可行。
//http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include <stack> #include <set> #include <bitset> #include <algorithm> using namespace std; typedef long long LL; #define gets(A) fgets(A, 1e8, stdin) const int INF = 0x3F3F3F3F, N = 10008, MOD = 1003, M = 1000000; const double EPS = 1e-6; int fa[N]; int Find(int x){ while(x!=fa[x]){ x=fa[x]; } return x; } void Union(int x,int y){ int fx=Find(x); int fy=Find(y); if(fx!=fy){ fa[fy]=fx; } } int head[N], tot; struct node{ int u, v, cap, next; }edge[M]; int cur[N], lev[N], s[N]; void init(){ memset(head, -1, sizeof(head)); tot = 0; } void add(int u, int v, int cap){ edge[tot].u = u; edge[tot].v = v; edge[tot].cap = cap; edge[tot].next = head[u]; head[u] = tot++; //反向弧 edge[tot].u = v; edge[tot].v = u; edge[tot].cap = 0; edge[tot].next = head[v]; head[v] = tot++; } bool bfs(int st, int des){ memset(lev, -1, sizeof(lev)); lev[st] = 0; queue<int> q; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && lev[v] == -1){ lev[v] = lev[u] + 1; q.push(v); if(v == des){ return true; } } } } return false; } //源点,汇点,点的数量 int dinic(int st, int des, int n){ int ans = 0; while(bfs(st, des)){ memcpy(cur, head, sizeof(int) * (n + 1)); int u = st, top = 0; while(true){ if(u == des){ int mini = INF, loc; for(int i = 0; i < top; i++){ if(mini > edge[s[i]].cap){ mini = edge[s[i]].cap; loc = i; } } for(int i = 0; i < top; i++){ edge[s[i]].cap -= mini; edge[s[i] ^ 1].cap += mini; } ans += mini; top = loc; u = edge[s[top]].u; } int &i = cur[u];//引用类型 for(; i != -1; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && lev[v] == lev[u] + 1){ break; } } if(i != -1){ s[top++] = i; u = edge[i].v; }else{ if(!top){ break; } lev[u] = -1; u = edge[s[--top]].u; } } } return ans; } std::vector<int> v[N]; int h[N]; int main(){ int n, m, k; while(cin >> n >> m >> k){ int st = 0; for(int i = 1; i <= n + 2; i++){ fa[i] = i; } for(int i = 1; i <= m; i++){ v[i].clear(); cin>>h[i]; int x; cin >> x; for(int j = 0; j < x; j++){ int tp; cin >> tp; if(tp == 0){ tp = n + 1; }else if(tp == -1){ tp = n + 2; } v[i].push_back(tp); if(j){ Union(v[i][j - 1], v[i][j]); } } if(h[i] == 0){ i--; m--; } } if((m == 0 ) || (Find(n + 1) != Find(n + 2))){ printf("0\\n"); continue; } for(int d = 1; ; d++){ init(); add(st, n + 1, k); for(int i = 1; i <= d; i++){ for(int j = 1; j <= n + 2; j++){ add((n + 2) * (i - 1) + j, (n + 2) * i + j, INF); } for(int j = 1; j <= m; j++){ int a = v[j][(i - 1) % v[j].size()]; int b = v[j][i % v[j].size()]; a = (n + 2) * (i - 1) + a; b = (n + 2) * i + b; add(a, b, h[j]); } } int ans = dinic(st, (n + 2) * (d + 1), (n + 2) * (d + 1) + 1); if(ans == k){ printf("%d\\n", d); break; } } } return 0; }
以上是关于星际转移问题(最大流 枚举)的主要内容,如果未能解决你的问题,请参考以下文章