网络流24题——星际转移问题(思维)

链接:https://www.oj.swust.edu.cn/oj/problem/show/1748

分析:这题最难的地方在于飞船的周期性,不同时间图不一样。。。考虑枚举天数,记Xn,m为第n天的第m个点,从Xn,m向Xn+1,l连一条边,m,l之间这一天有飞船,容量为飞船容量,然后从Xn,m向Xn+1,m连一条容量为无穷大,求从地球到月亮的最大流,当最大流>=k停止。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<queue>
  5 #include<cstring>
  6 using namespace std;
  7 const int maxn=1e3+5,INF=1e9;
  8 struct Edge{
  9     int from,to,cap,flow;
 10     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
 11 };
 12 struct ISAP{
 13     int n,s,t,flow;
 14     vector<Edge> edges;
 15     vector<int> G[maxn];
 16     bool vis[maxn];
 17     int d[maxn],cur[maxn],p[maxn],num[maxn];
 18 
 19     void init(int n){
 20         this->n=n;
 21         flow=0;
 22         edges.clear();
 23         for(int i=0;i<n;i++)G[i].clear();
 24     }
 25 
 26     void AddEdge(int from,int to,int cap){
 27         edges.push_back(Edge(from,to,cap,0));
 28         edges.push_back(Edge(to,from,0,0));
 29         G[from].push_back(edges.size()-2);
 30         G[to].push_back(edges.size()-1);
 31     }
 32 
 33     void BFS(){
 34         memset(vis,0,sizeof(vis));
 35         queue<int>Q;
 36         Q.push(t);
 37         d[t]=0;vis[t]=1;
 38         while(!Q.empty()){
 39             int x=Q.front();Q.pop();
 40             for(int i=0;i<G[x].size();i++){
 41                 Edge &e=edges[G[x][i]^1];
 42                 if(e.flow==e.cap)continue;
 43                 if(!vis[e.from]){
 44                     vis[e.from]=1;
 45                     d[e.from]=d[x]+1;
 46                     Q.push(e.from);
 47                 }
 48             }
 49         }
 50     }
 51 
 52     int Augmemt(){
 53         int x=t,a=INF;
 54         while(x!=s){
 55             Edge &e=edges[p[x]];
 56             a=min(a,e.cap-e.flow);
 57             x=edges[p[x]].from;
 58         }
 59         x=t;
 60         while(x!=s){
 61             edges[p[x]].flow+=a;
 62             edges[p[x]^1].flow-=a;
 63             x=edges[p[x]].from;
 64         }
 65         return a;
 66     }
 67 
 68     int Maxflow(int s,int t){
 69         this->s=s;this->t=t;
 70         BFS();
 71         memset(num,0,sizeof(num));
 72         for(int i=0;i<n;i++)num[d[i]]++;
 73         int x=s;
 74         memset(cur,0,sizeof(cur));
 75         while(d[s]<n){
 76             if(x==t){
 77                 flow+=Augmemt();
 78                 x=s;
 79             }
 80             int ok=0;
 81             for(int i=cur[x];i<G[x].size();i++){
 82                 Edge &e=edges[G[x][i]];
 83                 if(e.cap>e.flow&&d[x]==d[e.to]+1){
 84                     ok=1;
 85                     p[e.to]=G[x][i];
 86                     cur[x]=i;
 87                     x=e.to;
 88                     break;
 89                 }
 90             }
 91             if(!ok){
 92                 int m=n-1;
 93                 for(int i=0;i<G[x].size();i++){
 94                     Edge &e=edges[G[x][i]];
 95                     if(e.cap>e.flow)m=min(m,d[e.to]);
 96                 }
 97                 if(--num[d[x]]==0)break;
 98                 num[d[x]=m+1]++;
 99                 cur[x]=0;
100                 if(x!=s)x=edges[p[x]].from;
101             }
102         }
103         return flow;
104     }
105 }isap;
106 int n,m,k,day=0,moon=1000;
107 int fa[1005];
108 int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
109 struct SpaceShip{
110     int h,c;
111     vector<int> stop;
112 }ss[25];
113 inline int read(){
114     int t;
115     scanf("%d",&t);
116     if(t==-1)return moon;
117     return t;
118 }
119 int main(){
120 //    freopen("e:\\in.txt","r",stdin);
121     scanf("%d%d%d",&n,&m,&k);
122     isap.init(moon+1);
123     for(int i=0;i<=moon;i++)fa[i]=i;
124     for(int i=0;i<m;i++){
125         int stop;
126         scanf("%d%d",&ss[i].h,&ss[i].c);
127         for(int j=0;j<ss[i].c;j++){
128             stop=read();
129             ss[i].stop.push_back(stop);
130             if(j){
131                 int x=Find(stop),y=Find(ss[i].stop[0]);
132                 if(x!=y)fa[x]=y;
133             }
134         }
135     }
136     if(Find(0)!=Find(moon))cout<<0<<endl;
137     else{
138         while(isap.flow<k){
139             for(int i=1;i<=n;i++)isap.AddEdge(i+day*n,i+(day+1)*n,INF);
140             for(int i=0;i<m;i++){
141                 int u=ss[i].stop[day%ss[i].c]+day*n,v=ss[i].stop[(day+1)%ss[i].c]+(day+1)*n;
142                 if(ss[i].stop[day%ss[i].c]==0)u=0;
143                 if(ss[i].stop[(day+1)%ss[i].c]==moon)v=moon;
144                 if(ss[i].stop[(day+1)%ss[i].c]==0||ss[i].stop[day%ss[i].c]==moon)continue;
145                 isap.AddEdge(u,v,ss[i].h);
146             }
147             isap.Maxflow(0,moon);
148             day++;
149         }
150         cout<<day<<endl;
151     }
152     return 0;
153 }

 

转载于:https://www.cnblogs.com/7391-KID/p/7448332.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值