星际转移问题(最大流 枚举)

使用并查集判断有无解,若有解枚举天数若最大流等于人数则可行。

//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;
}
时间: 2025-01-09 04:59:20

星际转移问题(最大流 枚举)的相关文章

线性规划与网络流24题●09方格取数问题&amp;13星际转移问题

●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为"技术"不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下参考题解,说是本题要求二分图点权最大独立集,然后可以由结论:"最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流"转化到求最大流(我真的很懵逼,但又感觉很有道理): 下面附上solution:(自己领悟吧) (不懂

[网络流24题] 13. 星际转移问题 解题报告

13.星际转移问题 题意 有 \(n\) 个太空站, \(m\) 艘太空船, 太空船 \(i\) 一次能容下 \(h_i\) 个人, 每艘太空船会按照自己的航线循环行驶, 每行驶一个站点需要一个单位时间, 求从节点 \(0\) 到节点 \(n+1\) 所需的最小时间. 思路 一道一开始完全没有思路的题, 后来发现姆爷又发了新专, 果断地剁手后听了一会, 这道题就想出来了...... 总思路是把每个太空站都按时间分为若干个节点, 也就是说, 每加一个单位时间, 我们就把这总共 \(n+2\) 个点

[CTSC1999][网络流24题] 星际转移

36. [CTSC1999][网络流24题] 星际转移 ★★★☆   输入文件:home.in   输出文件:home.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了. 于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未 知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有n个太空站 位于地球与月球之间,且有m 艘公共交通太空船在其间

Luogu 星际转移问题(枚举 + 最大流)

题目: luogu 2754 看到最短时间, 很自然地想到了最小费用最大流, 但这么做是有漏洞的. 因为只要能够运载 k 个人就可以, 不一定是最大流, 最大流的时间有可能比运输 k 个人的时间长. 你看题目给的这个数据范围很小, 而且不能用费用流做, 只能用最大流, 可见要枚举时间, 按照时间来分层建图. 就是说每次时间++, 连一层这个时间里的边, 直到最大流 >= k, 输出答案. 建模如下图, 以题目中样例画的, 蓝色的边是样例中飞船的运动路线, 红色的边是最终的答案路径. 原文地址:h

【网络流24题】No. 13 星际转移问题 (网络判定 最大流)

[题意] 由于人类对自然资源的消耗, 人们意识到大约在 2300 年之后, 地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民. 令人意想不到的是, 2177 年冬由于未知的原因, 地球环境发生了连锁崩溃, 人类必须在最短的时间内迁往月球. 现有 n 个太空站位于地球与月球之间,且有 m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人, 而每艘太空船 i 只可容纳 H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如: (1, 3, 4)表示该太空船将周期性地停靠

洛谷 P2754 星际转移问题【最大流】

判无解的方法非常粗暴:快T了还是没有合法方案,就是无解. 然后枚举答案,对于每一天都建一套太空站,s连地球,t连月球,上一天的太空站连向这一天的太空站,流量均为inf.然后对于每个飞船,上一天的停靠站向这一天的停靠站连边,流量为p.每次新增一天都新建一套,然后跑一次dinic加给tot,等tot>=k,当前枚举的天数就是答案. #include<iostream> #include<cstdio> #include<cstring> #include<que

[CTSC1999]【网络流24题】星际转移

Description 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有n个太空站 位于地球与月球之间,且有m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人,而每艘太空船i 只可容纳H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站134134

【网络流24题】星际转移问题

Description 由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有 n 个太空站位于地球与月球之间,且有 m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人,而每艘太空船 i 只可容纳 H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站

星际转移(cogs 736)

?问题描述: 由于人类对自然资源的消耗,人们意识到大约在2300 年之后,地球就不能再居住了.于是在月球上建立了新的绿地,以便在需要时移民.令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球.现有n个太空站位于地球与月球之间,且有m 艘公共交通太空船在其间来回穿梭.每个太空站可容纳无限多的人,而每艘太空船i 只可容纳H[i]个人.每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站134134134-.每