poj 2112 Optimal Milking 奶牛

题目链接: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\n",l);
171 
172     }
173     return 0;
174 }

 

转载于:https://www.cnblogs.com/TreeDream/p/6602018.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值