题目链接:http://poj.org/problem?id=2112
题意:K个产奶机,C头奶牛,每个产奶机最多可供M头奶牛使用;并告诉了产奶机、奶牛之间的两两距离Dij(0<=i,j<K+C)。
分析:
肯定不是费用流,是这样的,先跑一遍floyd,二分结果,满足就有这条边,否则就没有,看可不可以跑出c头奶牛。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <algorithm> 7 8 using namespace std; 9 10 #define inf 0x3f3f3f3f 11 const int maxn = 1000; 12 13 struct Edge 14 { 15 int from,to,cap,flow; 16 }; 17 18 struct Dinic 19 { 20 int n,m,s,t; 21 vector<Edge> edge; 22 vector<int> G[maxn]; 23 bool vis[maxn]; 24 int d[maxn]; 25 int cur[maxn]; 26 27 void init() 28 { 29 for(int i=0;i<maxn;i++) 30 G[i].clear(); 31 edge.clear(); 32 memset(d,0,sizeof(d)); 33 memset(vis,0,sizeof(vis)); 34 memset(cur,0,sizeof(cur)); 35 } 36 37 void AddEdge (int from,int to,int cap) 38 { 39 edge.push_back((Edge){from,to,cap,0}); 40 edge.push_back((Edge){to,from,0,0}); 41 m = edge.size(); 42 G[from].push_back(m-2); 43 G[to].push_back(m-1); 44 } 45 46 bool BFS() 47 { 48 memset(vis,0,sizeof(vis)); 49 queue<int> Q; 50 Q.push(s); 51 d[s] = 0; 52 vis[s] = 1; 53 while(!Q.empty()) 54 { 55 int x = Q.front(); 56 Q.pop(); 57 for(int i=0; i<G[x].size(); i++) 58 { 59 Edge & e = edge[G[x][i]]; 60 if(!vis[e.to]&&e.cap>e.flow) 61 { 62 vis[e.to] = 1; 63 d[e.to] = d[x] + 1; 64 Q.push(e.to); 65 } 66 } 67 } 68 return vis[t]; 69 } 70 71 long long DFS(int x,int a) 72 { 73 if(x==t||a==0) return a; 74 long long flow = 0,f; 75 for(int & i = cur[x]; i<G[x].size(); i++) 76 { 77 Edge & e = edge[G[x][i]]; 78 if(d[x] + 1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0) 79 { 80 e.flow +=f; 81 edge[G[x][i]^1].flow -=f; 82 flow +=f; 83 a-=f; 84 if(a==0) break; 85 } 86 } 87 return flow; 88 } 89 90 int Maxflow (int s,int t) { 91 this->s = s;this->t = t; 92 int flow = 0; 93 while(BFS()) { 94 memset(cur,0,sizeof(cur)); 95 flow+=DFS(s,inf); 96 } 97 return flow; 98 } 99 }sol; 100 101 102 int dist[maxn][maxn]; 103 104 int main() 105 { 106 int k,c,m; 107 while(~scanf("%d%d%d",&k,&c,&m)) 108 { 109 110 int l = inf,r=0; 111 int z = k+c; 112 for(int i=1; i<=z; i++) 113 { 114 for(int j=1; j<=z; j++) 115 { 116 scanf("%d",&dist[j][i]); 117 if(dist[j][i] == 0) 118 { 119 dist[j][i] = inf; 120 } 121 } 122 } 123 124 for(int kk=1; kk<=z; kk++) 125 { 126 for(int i=1; i<=z; i++) 127 { 128 for(int j=1; j<=z; j++) 129 { 130 if(dist[k][j]<inf&&dist[i][j]>dist[i][k]+dist[k][j]) 131 dist[i][j] =dist[i][kk]+dist[kk][j]; 132 } 133 } 134 } 135 136 for(int i=1; i<=z; i++) 137 { 138 for(int j=i+1; j<=z; j++) 139 { 140 if(dist[i][j]<inf) 141 l = min(l,dist[i][j]),r = max(r,dist[i][j]); 142 } 143 } 144 145 int s = 0,t=z+1; 146 while(l<r) 147 { 148 int mid = l+(r-l)/2; 149 sol.init(); 150 151 for(int i=k+1;i<=k+c;i++) { 152 sol.AddEdge(s,i,1); 153 for(int j=1;j<=k;j++) { 154 if(dist[i][j]<=mid) { 155 sol.AddEdge(i,j,inf); 156 sol.AddEdge(j,i,inf); 157 } 158 } 159 } 160 161 for(int i=1;i<=k;i++) 162 sol.AddEdge(i,t,m); 163 164 if(sol.Maxflow(0,z+1)>=c) 165 { 166 r = mid; 167 } 168 else l = mid+1; 169 } 170 printf("%d ",l); 171 172 } 173 return 0; 174 }