zoukankan      html  css  js  c++  java
  • 【网络流24题】星际转移问题

    Description

    由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了。于是在月球上建立了新的绿地,以便在需要时移民。令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球。现有 n 个太空站位于地球与月球之间,且有 m 艘公共交通太空船在其间来回穿梭。每个太空站可容纳无限多的人,而每艘太空船 i 只可容纳 H[i]个人。每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4)表示该太空船将周期性地停靠太空站 134134134…。每一艘太空船从一个太空站驶往任一太空站耗时均为 1。人们只能在太空船停靠太空站(或月球、地球)时上、下船。初始时所有人全在地球上,太空船全在初始站。试设计一个算法,找出让所有人尽快地全部转移到月球上的运输方案。

    对于给定的太空船的信息,找到让所有人尽快地全部转移到月球上的运输方案。

    Solution

    建立时间分层图,即把每一个点再每一个时间都对应到一个点上
    然后枚举时间加点加边
    设地球为(n+1),月球为(n+2)
    ((S,n+1,inf),(T,n+1,inf))
    ((i,i',inf)) 即每一个时间向下一个时间相对应的点连边,相当于在某个点停留
    ((x,y',h[i])) 枚举每一艘太空船在这一个时间的航线((x,y)),对应连边
    直到最大流大于等于(k),当前时间就是答案

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1005,M=100005,inf=2e8;
    int head[N],nxt[M],to[M],num=1,dis[M],n,m,K;
    void link(int x,int y,int z){
    	nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;
    	nxt[++num]=head[y];to[num]=x;head[y]=num;dis[num]=0;
    }
    int c[N],a[N][N],h[N],dep[N],S,T;queue<int>q;
    inline bool bfs(){
    	memset(dep,0,sizeof(dep));
    	q.push(S);dep[S]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=head[x];i;i=nxt[i]){
    			int u=to[i];
    			if(dep[u] || dis[i]<=0)continue;
    			dep[u]=dep[x]+1;q.push(u);
    		}
    	}
    	return dep[T];
    }
    inline int dfs(int x,int flow){
    	if(x==T || !flow)return flow;
    	int u,tot=0,t;
    	for(int i=head[x];i;i=nxt[i]){
    		u=to[i];
    		if(dep[u]!=dep[x]+1 || dis[i]<=0)continue;
    		t=dfs(u,min(flow,dis[i]));
    		dis[i]-=t;dis[i^1]+=t;
    		flow-=t;tot+=t;
    		if(!flow)break;
    	}
    	if(!tot)dep[x]=-1;
    	return tot;
    }
    inline int Dinic(){
    	int tot=0,t;
    	while(bfs()){
    		t=dfs(S,inf);
    		while(t)tot+=t,t=dfs(S,inf);
    	}
    	return tot;
    }
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      scanf("%d%d%d",&n,&m,&K);T=N-1;
      for(int i=1;i<=m;i++){
    	  scanf("%d%d",&h[i],&c[i]);
    	  for(int j=1;j<=c[i];j++){
    		  scanf("%d",&a[i][j]);
    		  if(a[i][j]==-1)a[i][j]=n+2;
    		  if(a[i][j]==0) a[i][j]=n+1;
    	  }
      }
      n+=2;
      link(S,n-1,inf);link(n,T,inf);
      int x,y,t=0;
      for(int o=1;o<=50;o++){
    	  for(int i=1;i<=n;i++)link((o-1)*n+i,o*n+i,inf);
    	  link(S,o*n+n-1,inf);link(o*n+n,T,inf);
    	  for(int i=1;i<=m;i++){
    		  x=o%c[i];if(!x)x=c[i];
    		  y=o%c[i]+1;
    		  link((o-1)*n+a[i][x],o*n+a[i][y],h[i]);
    	  }
    	  t+=Dinic();
    	  if(t>=K)printf("%d
    ",o),exit(0);
      }
      puts("0");
      return 0;
    }
    
    
  • 相关阅读:
    CLR的黑暗面——栈与引用对象
    delegate的另类玩法
    一个比较bt的xslt
    关于string
    jQuery核心讲解
    Linux环境进程间通信(二):信号(上)
    ubuntu10.10 轻松安装 Nvidia 官方驱动
    Linux环境进程间通信(二): 信号(下)
    Linux 信号signal处理机制
    java.lang.ProcessBuilder类和java.lang.Process类
  • 原文地址:https://www.cnblogs.com/Yuzao/p/8447434.html
Copyright © 2011-2022 走看看