• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
kito's blog
Dreaming away.
博客园    首页    新随笔    联系   管理    订阅  订阅

cogs 736 星际转移 最大流

cogs 736 星际转移
题解:
从小到大枚举答案days,然后网络流验证是否可以全部运走。假设当前验证的答案为days,那么我们就将太空船和太空站都拆成days+1个点,设编号分别为boat[i][1days+1],station[i][1days+1]。

  1. 如果说boat[i]在第j天在地球,那么此时boat[i][j]可以接受流量上限为H[i]的人上船,因此从S向boat[i][j]连边,容量H[i]。
  2. 如果boat[i]第j天在月球,此时boat[i][j]可以释放上限为H[i]的流量,因此boat[i][j]到T连边,容量H[i]。
  3. boat[i]第j天在太空站station[k],那么双方可以进行交换,boat[i][j]与station[k][j]互相连边,容量均为H[i]。
  4. 注意到boat[i]在第j天的流量是可以下传到第j+1天的,所以boat[i][j]向boat[i][j+1]连边容量为H[i]。
  5. 注意到太空站也是可以下传的,station[i][j]向station[i][j+1]连容量为INF的边。

然后跑一下最大流,判断是否最大流小于人数,如果小于,则days再加一,在上一次的图上再加入一层点接着跑,否则结束输出days即可。

至于判断无解,我是判断如果days=1000都没结束就输出无解。

code

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define fcl fclose(stdin); fclose(stdout); return 0
int n,m,K,days,S,T,res=0,cnt;
int H[30],r[30],t[30][20];
const int INF=0x7f7f7f7f;
struct EDGE{
	int to,next,flow;
}edge[1000010];
int head[100010],tot=1;
inline void AddEdge(int a,int b,int c){
	edge[++tot].to=b;
	edge[tot].flow=c;
	edge[tot].next=head[a];
	head[a]=tot;
}
inline void Add(int a,int b,int c){
	AddEdge(a,b,c); AddEdge(b,a,0);
}
int cur[100010],dis[100010],Q[100010];
#define ty (edge[x].to)
bool Bfs(){
	memset(dis,0x7f,(cnt+1)<<2); dis[S]=0;
	int s=1,t=1,u; Q[1]=S;
	while(s<=t){
		u=Q[s++];
		for(int x=head[u];x;x=edge[x].next)
			if(edge[x].flow&&dis[ty]==INF)
				dis[ty]=dis[u]+1,Q[++t]=ty;
	}
	return dis[T]!=INF;
}
int Dfs(int u,int a){
	if(u==T||a==0) return a;
	int f2=0,f;
	for(int& x=cur[u];x;x=edge[x].next){
		if(edge[x].flow&&dis[ty]==dis[u]+1){
			f=Dfs(ty,min(a,edge[x].flow));
			edge[x].flow-=f; edge[x^1].flow+=f;
			f2+=f; a-=f;
			if(a==0) break;
		}
	}
	return f2;
}
bool Judge(){
	for(int i=1;i<=m;++i){
		int x=days%r[i];
		if(t[i][x]==0) Add(S,cnt+i,H[i]);
		else if(t[i][x]==-1) Add(cnt+i,T,H[i]);
		else AddEdge(cnt+i,cnt+m+t[i][x],INF),Add(cnt+m+t[i][x],cnt+i,INF);
		Add(cnt+i,cnt+i+n+m,H[i]);
	}
	for(int i=1;i<=n;++i) Add(cnt+m+i,cnt+n+m+m+i,INF);
	cnt+=(n+m);
	while(Bfs()){
		memcpy(cur,head,(cnt+1)<<2);
		res+=Dfs(S,INF);
	}
	if(res<K) return true;
	return false;
}
int main(){
	freopen("home.in","r",stdin);
	freopen("home.out","w",stdout);
	
	scanf("%d%d%d",&n,&m,&K);
	S=1,T=2,cnt=2;
	for(int i=1;i<=m;++i){
		scanf("%d%d",&H[i],&r[i]);
		for(int j=0;j<r[i];++j) scanf("%d",&t[i][j]);
	}
	if(K==0){puts("0");fcl;}
	for(;days<1000&&Judge();++days);
	if(days==1000) days=0;
	printf("%d\n",days);
	fcl;
}
posted @ 2017-07-08 06:38  kito  阅读(204)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3