LA 2957 最大流,最短时间,输出路径

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=159&page=show_problem&problem=958

题意:n个星球,用最短的时间把k个超级计算机从s运到t;

其中,每个隧道是双向的,一个隧道里面只能有一个飞船在使用,一个飞船上只有一台计算机。

分析:

一个隧道只能给一个飞船用,那么假设需要t天,那么可以这样建图:

u结点,拆成t+1个,分别是 u0,u1,u2,...,ut;

u0是u的初始状态,ui是u在第i天的状态,那么建图就是:

a结点到b结点,ai 到 bi+1 一条容量为1的边,bi 到 ai+1 的容量为1的一条边。

对于每个结点,都有ui到ui+1 的容量是无穷大,因为可以停留。

一天一天增加结点,终点也发生变化,流量直到为k,就结束了。

然后输出路径:

遍历原图的上的每一条边,注意edges是残余网络,idx+=2;这才加了一条边。

问题问的路径是(A,B)编号为A的飞机,到达行星 B,行星B就是有流量的那一条边都后面那个结点。那么,编号A怎么求呢?

可以遍历一下这k个飞机,如果 j 所在的位置location[j] = a[i] 的话,就ok了。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int maxn = 5000+10;
  6 const int INF = 0x3f3f3f3f;
  7 
  8 struct Edge{
  9     int from,to,cap,flow;
 10 };
 11 
 12 bool operator < (const Edge& a,const Edge& b) {
 13     return a.from < b.from||(a.from==b.from&&a.to<b.to);
 14 }
 15 
 16 struct Dinic {
 17     int n,m,s,t;
 18     vector<Edge> edges;
 19     vector<int> G[maxn];
 20     bool vis[maxn];
 21     int d[maxn];
 22     int cur[maxn];
 23 
 24     void init() {
 25         edges.clear();
 26     }
 27 
 28     void clearNodes(int a,int b) {
 29         for(int i=a;i<=b;i++)
 30             G[i].clear();
 31     }
 32 
 33     void AddEdge(int from,int to,int cap) {
 34         edges.push_back((Edge){from,to,cap,0});
 35         edges.push_back((Edge){to,from,0,0});
 36         m = edges.size();
 37         G[from].push_back(m-2);
 38         G[to].push_back(m-1);
 39     }
 40 
 41     bool BFS() {
 42         memset(vis,0,sizeof(vis));
 43         queue<int> Q;
 44         Q.push(s);
 45         vis[s] = 1;
 46         d[s] = 0;
 47         while(!Q.empty()) {
 48             int x = Q.front();  Q.pop();
 49             for(int i=0;i<G[x].size();i++) {
 50                 Edge& e = edges[G[x][i]];
 51                 if(!vis[e.to]&&e.cap>e.flow) {
 52                     vis[e.to] = 1;
 53                     d[e.to] = d[x] + 1;
 54                     Q.push(e.to);
 55                 }
 56             }
 57         }
 58         return vis[t];
 59     }
 60 
 61     int DFS(int x,int a) {
 62         if(x==t||a==0) return a;
 63         int flow = 0,f;
 64         for(int& i=cur[x];i<G[x].size();i++) {
 65             Edge& e = edges[G[x][i]];
 66             if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0) {
 67                 e.flow +=f;
 68                 edges[G[x][i]^1].flow-=f;
 69                 flow+=f;
 70                 a-=f;
 71                 if(a==0) break;
 72             }
 73         }
 74         return flow;
 75     }
 76 
 77     int Maxflow(int s,int t,int limit) {
 78         this->s = s;
 79         this->t = t;
 80         int flow = 0;
 81         while(BFS()) {
 82             memset(cur,0,sizeof(cur));
 83             flow +=DFS(s,limit-flow);
 84             if(flow==limit) break;
 85         }
 86         return flow;
 87     }
 88 };
 89 
 90 Dinic g;
 91 
 92 int main()
 93 {
 94     int n,m,k,s,t;
 95     int u[maxn],v[maxn];
 96 
 97     while(~scanf("%d%d%d%d%d",&n,&m,&k,&s,&t)) {
 98         for(int i=0;i<m;i++) {
 99             scanf("%d%d",&u[i],&v[i]);
100         }
101         g.init();
102         int day = 1;
103         g.clearNodes(0,n-1);
104         int flow = 0;
105         for(;;) {
106             g.clearNodes(day*n,day*n+n-1);
107             for(int i=0;i<n;i++)
108                 g.AddEdge((day-1)*n+i,day*n+i,INF);
109             for(int i=0;i<m;i++) {
110                 g.AddEdge((day-1)*n+u[i]-1,day*n+v[i]-1,1);
111                 g.AddEdge((day-1)*n+v[i]-1,day*n+u[i]-1,1);
112             }
113             flow+=g.Maxflow(s-1,day*n+t-1,k-flow);
114             if(flow==k) break;
115             day++;
116         }
117 
118         printf("%d
",day);
119 
120         int idx = 0;
121         vector<int> location(k,s);
122 
123         for(int d=1;d<=day;d++) {
124             idx +=n*2;
125             vector<int> moved(k,0);
126             vector<int> a,b;
127 
128             for(int i=0;i<m;i++) {
129                 int f1 = g.edges[idx].flow; idx+=2;
130                 int f2 = g.edges[idx].flow; idx+=2;
131                 if(f1==1&&f2==0) {
132                     a.push_back(u[i]);
133                     b.push_back(v[i]);
134                 }
135                 if(f1==0&&f2==1) {
136                     a.push_back(v[i]);
137                     b.push_back(u[i]);
138                 }
139             }
140 
141             printf("%d",a.size());
142             for(int i=0;i<a.size();i++) {
143                 for(int j=0;j<k;j++) {  //找到具体是哪一个飞船
144                     if(!moved[j]&&location[j]==a[i]) {
145                         printf(" %d %d",j+1,b[i]);
146                         moved[j] = 1;
147                         location[j] = b[i];
148                         break;
149                     }
150                 }
151             }
152             printf("
");
153 
154         }
155 
156     }
157 
158     return 0;
159 }
原文地址:https://www.cnblogs.com/TreeDream/p/6539460.html