P2754 星际转移问题

题解:利用分层图思想加入时间概念,第0天地球编号设为0,月球编号设为n+1,空间站编号在1到n之间。对于每一天都新建n+2个点表示不同天不同地方的情况,这样加入了时间概念。源点与第0天的地球建立一条容量k的边表示初始所有人在地球上,不同点与上一天相同点建立一条容量正无穷的边表示任意地方可以容纳无限多的人,每一天的月球与汇点建立一条正无穷的点,因为本题只加边所以可在上一天的残余网络上增广,直到汇点的容量大于等于k位置。判断无法到达用并查集判断即可。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=760,M=(2*N+1e3)*2,inf=1e9;
  4 int h[N],e[M],ne[M],f[M],idx;
  5 int d[N],cur[N],p[30];
  6 int n,m,k,S,T;
  7 struct node
  8 {
  9     int sum,r,id[30];
 10 }ship[30];
 11 int find(int x)
 12 {
 13     if(p[x]!=x)p[x]=find(p[x]);
 14     return p[x];
 15 }
 16 int get(int day,int u)
 17 {
 18     return day*(n+2)+u;
 19 }
 20 void add(int a,int b,int c)
 21 {
 22     ne[idx]=h[a],e[idx]=b,f[idx]=c,h[a]=idx++;
 23     ne[idx]=h[b],e[idx]=a,f[idx]=0,h[b]=idx++;
 24 }
 25 bool bfs()
 26 {
 27     memset(d,-1,sizeof d);
 28     queue<int>q;
 29     q.push(S);
 30     cur[S]=h[S];
 31     d[S]=0;
 32     while(q.size())
 33     {
 34         int t=q.front();
 35         q.pop();
 36         for(int i=h[t];i!=-1;i=ne[i])
 37         {
 38             int j=e[i];
 39             if(d[j]==-1&&f[i])
 40             {
 41                 d[j]=d[t]+1;
 42                 cur[j]=h[j];
 43                 if(j==T)return true;
 44                 q.push(j);
 45             }
 46         }
 47     }
 48     return false;
 49 }
 50 int find(int u,int limit)
 51 {
 52     if(u==T)return limit;
 53     int flow=0;
 54     for(int i=cur[u];i!=-1&&flow<limit;i=ne[i])
 55     {
 56         int j=e[i];
 57         cur[u]=i;
 58         if(d[j]==d[u]+1&&f[i])
 59         {
 60             int t=find(j,min(f[i],limit-flow));
 61             if(!t)d[j]=-1;
 62             f[i]-=t,f[i^1]+=t,flow+=t;
 63         }
 64     }
 65     return flow;
 66 }
 67 int dinic()
 68 {
 69     int r=0,flow;
 70     while(bfs())while(flow=find(S,inf))r+=flow;
 71     return r;
 72 }
 73 int main()
 74 {
 75     memset(h,-1,sizeof h);
 76     cin>>n>>m>>k;
 77     S=N-1,T=N-2;
 78     for(int i=0;i<=n+1;i++)p[i]=i;
 79     for(int i=0;i<m;i++)
 80     {
 81         int x,y;
 82         scanf("%d%d",&x,&y);
 83         ship[i].sum=x;
 84         ship[i].r=y;
 85         for(int j=0;j<y;j++)
 86         {
 87             int id;
 88             scanf("%d",&id);
 89             if(id==-1)id=n+1;
 90             ship[i].id[j]=id;
 91             if(j)
 92             {
 93                 int de=ship[i].id[j-1];
 94                 p[find(de)]=find(id);
 95             }
 96         }
 97     }
 98     if(find(0)!=find(n+1))puts("0");
 99     else
100     {
101         add(S,get(0,0),k);
102         add(get(0,n+1),T,inf);
103         int res=0,day=1;
104         while(1)
105         {
106             for(int i=0;i<=n+1;i++)
107             add(get(day-1,i),get(day,i),inf);
108             add(get(day,n+1),T,inf);
109             for(int i=0;i<m;i++)
110             {
111                 int r=ship[i].r;
112                 int x=get(day-1,ship[i].id[(day-1)%r]);
113                 int y=get(day,ship[i].id[day%r]);
114                 add(x,y,ship[i].sum);
115             }
116             res+=dinic();
117             if(res>=k)break;
118             day++;
119         }
120         printf("%d\n",day);
121     }
122 }

 

posted @ 2020-09-15 15:14  cumtljz  阅读(205)  评论(0编辑  收藏  举报