zoukankan      html  css  js  c++  java
  • 【网络流24题】No. 13 星际转移问题 (网络判定 最大流)

    【题意】

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

    输入文件示例
    input.txt
    2 2 1
    1 3 0 1 2
    1 3 1 2 –1

    输出文件示例
    output.txt
    5

    【分析】

      这题跟LA2957 很像。应该是很经典的模型。

      很容易想到要二分然后判定,但其实枚举更好,按顺序枚举的话,可以不重新建图,直接加边,继续跑,前面的题目中我也打过了的。

      然后拆点,假设枚举到d天,那么每个站就有d个点,然后如果有一个太空船第d天从u->v,那么u(d)->v(d+1),容量为太空船容量。即图上的点表示太空站,图上的边表示太空船。

      然后跑最大流。

      其实有点难打啊,这一题。我还用了vector,然后不连通其实要特判,不过我是加了上边界A掉的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<cmath>
      8 #include<vector>
      9 #include<map>
     10 using namespace std;
     11 #define Maxn 4100
     12 #define INF 0xfffffff
     13 
     14 struct node
     15 {
     16     int x,y,f,o,next;
     17 }t[Maxn*1010];int len;
     18 int first[Maxn];
     19 int n,m,k;
     20 
     21 int mymin(int x,int y) {return x<y?x:y;}
     22 int mymax(int x,int y) {return x>y?x:y;}
     23 
     24 void ins(int x,int y,int f)
     25 {
     26     t[++len].x=x;t[len].y=y;t[len].f=f;
     27     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     28     t[++len].x=y;t[len].y=x;t[len].f=0;
     29     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     30 }
     31 
     32 int st,ed;
     33 queue<int > q;
     34 int dis[Maxn];
     35 bool bfs()
     36 {
     37     while(!q.empty()) q.pop();
     38     memset(dis,-1,sizeof(dis));
     39     q.push(st);dis[st]=0;
     40     while(!q.empty())
     41     {
     42         int x=q.front();
     43         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     44         {
     45             int y=t[i].y;
     46             if(dis[y]==-1)
     47             {
     48                 dis[y]=dis[x]+1;
     49                 q.push(y);
     50             }
     51         }
     52         q.pop();
     53     }
     54     if(dis[ed]==-1) return 0;
     55     return 1;
     56 }
     57 
     58 int ffind(int x,int flow)
     59 {
     60     if(x==ed) return flow;
     61     int now=0;
     62     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     63     {
     64         int y=t[i].y;
     65         if(dis[y]==dis[x]+1)
     66         {
     67             int a=ffind(y,mymin(flow-now,t[i].f));
     68             t[i].f-=a;
     69             t[t[i].o].f+=a;
     70             now+=a;
     71         }
     72         if(now==flow) break;
     73     }
     74     if(now==0) dis[x]=-1;
     75     return now;
     76 }
     77 
     78 void output()
     79 {
     80     for(int i=1;i<=len;i+=2)
     81      printf("%d->%d %d
    ",t[i].x,t[i].y,t[i].f);
     82     printf("
    ");
     83 }
     84 
     85 int max_flow()
     86 {
     87     int ans=0;
     88     while(bfs())
     89     {
     90         ans+=ffind(st,INF);
     91     }
     92     return ans;
     93 }
     94 
     95 int hp[110],rl[110][110],cnt=2,add;
     96 vector<int > num[110];
     97 
     98 bool check(int x)
     99 {
    100     for(int i=1;i<=n;i++) num[i].push_back(++cnt);
    101     num[0].push_back(1);num[n+1].push_back(2);
    102     for(int i=1;i<=m;i++)
    103     {
    104         int y=rl[i][(x-1)%rl[i][0]+1],z=rl[i][x%(rl[i][0])+1];
    105         if(z==0||y==n+1) continue;
    106         y=num[y][x];z=num[z][x+1];
    107         ins(y,z,hp[i]);
    108     }
    109     for(int i=1;i<=n;i++) ins(num[i][x],num[i][x+1],INF);
    110     int now=max_flow();
    111     add+=now;
    112     return add>=k;
    113 }
    114 
    115 int main()
    116 {
    117     scanf("%d%d%d",&n,&m,&k);
    118     for(int i=1;i<=m;i++)
    119     {
    120         scanf("%d%d",&hp[i],&rl[i][0]);
    121         for(int j=1;j<=rl[i][0];j++)
    122         {
    123             scanf("%d",&rl[i][j]);
    124             // printf("%d
    ",rl[i][j]);
    125             if(rl[i][j]==-1) rl[i][j]=n+1;
    126         }
    127     }
    128     for(int i=1;i<=m;i++) num[i].clear();
    129     for(int i=0;i<=n+1;i++) num[i].push_back(0);//00000
    130     int ans=0;st=1;ed=2;
    131     for(int i=1;i<=n;i++) num[i].push_back(++cnt);
    132     num[0].push_back(1);num[n+1].push_back(2);
    133     add=0;
    134     while(1)
    135     {
    136         ans++;
    137         if(check(ans)) {printf("%d
    ",ans);break;}
    138         if(ans>100) {printf("0
    ");break;}
    139     }
    140     
    141     return 0;
    142 }
    View Code

    表示边也不知道要开多少,就开了好大好大。。

    2016-11-04 22:04:54

    对了,这里有个有点良心的网站可以交24题,然而,还是没有SPJ。。。

    http://oi.nks.edu.cn/status

  • 相关阅读:
    项目开发基础概念
    django 对接elasticsearch实现全文检索
    win10安装docker
    Mac VMware Fusion 中修改 centos7 虚拟机的磁盘空间、扩容
    CentOS 7下 YUM 本地仓库的搭建
    mac与虚拟机传输文件
    mac和windows快速锁定电脑
    rpm -qa详解
    虚拟机安装centos6
    mac与iPhone互传文件
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6031836.html
Copyright © 2011-2022 走看看