题意: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 }