使用并查集判断有无解,若有解枚举天数若最大流等于人数则可行。
//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;
}
原文:http://www.cnblogs.com/IMGavin/p/6387415.html