poj2112 二分最大流+Floyd

来源:互联网 发布:新概念背诵200遍 知乎 编辑:程序博客网 时间:2024/05/29 16:48
题意:
     一个农场主有一些奶牛,和一些机器,每台机器有自己的服务上限,就是一天最多能给多少头奶牛挤奶,给你任意两点的距离,问你让所有的奶牛都被挤奶时,奶牛于机器最远距离的最近是多少。

思路:

      求最远的最近,二分,然后用最大流去判断是否所有的奶牛都被挤奶了,简单题目,不多解释了,还有注意一点就是二分前记得Floyd一下,他没说给的是最短距离。


#include<stdio.h>#include<string.h>#include<queue>#define N_node 250#define N_edge 150000#define INF 1000000000using namespace std;typedef struct{   int to ,next ,cost;}STAR;typedef struct{   int x ,t;}DEP;STAR E[N_edge];DEP xin ,tou;int list[N_node] ,listt[N_node] ,tot;int deep[N_node] ,map[N_node][N_node];void add(int a ,int b ,int c){   E[++tot].to = b;   E[tot].cost = c;   E[tot].next = list[a];   list[a] = tot;      E[++tot].to = a;   E[tot].cost = 0;   E[tot].next = list[b];   list[b] = tot;}int minn(int x ,int y){   return x < y ? x : y;}bool BFS_Deep(int s ,int t ,int n){   memset(deep ,255 ,sizeof(deep));   xin.x = s ,xin.t = 0;   deep[xin.x] = xin.t;   queue<DEP>q;   q.push(xin);   while(!q.empty())   {      tou = q.front();      q.pop();      for(int k = list[tou.x] ;k ;k = E[k].next)      {         xin.x = E[k].to;         xin.t = tou.t + 1;         if(deep[xin.x] != -1 || !E[k].cost)         continue;         deep[xin.x] = xin.t;         q.push(xin);      }   }   for(int i = 0 ;i <= n ;i ++)   listt[i] = list[i];   return deep[t] != -1;}int DFS_Flow(int s ,int t ,int flow){   if(s == t) return flow;   int nowflow = 0;   for(int k = listt[s] ;k ;k = E[k].next)   {      int to = E[k].to ,c = E[k].cost;      listt[s] = k;      if(deep[to] != deep[s] + 1 || !E[k].cost)      continue;      int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));      nowflow += tmp;      E[k].cost -= tmp;      E[k^1].cost += tmp;      if(nowflow == flow) break;   }   if(!nowflow) deep[s] = 0;   return nowflow;}int DINIC(int s ,int t ,int n){   int ans = 0;   while(BFS_Deep(s ,t ,n))   {      ans += DFS_Flow(s ,t ,INF);   }   return ans;}void Floyd(int n){   for(int k = 1 ;k <= n ;k ++)   for(int i = 1 ;i <= n ;i ++)   for(int j = 1 ;j <= n ;j ++)   map[i][j] = minn(map[i][j] ,map[i][k] + map[k][j]);}bool ok(int mid ,int K ,int C ,int M){   memset(list ,0 ,sizeof(list));   tot = 1;   for(int i = 1 ;i <= K ;i ++)   add(0 ,i ,M);   for(int i = 1 ;i <= K ;i ++)   for(int j = K + 1 ;j <= K + C ;j ++)   if(mid >= map[i][j]) add(i ,j ,1);   for(int i = 1 ;i <= C ;i ++)   add(i + K ,K + C + 1 ,1);   return DINIC(0 ,C + K + 1 ,C + K + 1) == C;}         int main (){   int K ,C ,M;   int i ,j ,a;   while(~scanf("%d %d %d" ,&K ,&C ,&M))   {      for(i = 1 ;i <= K + C ;i ++)      for(j = 1 ;j <= K + C ;j ++)      {         scanf("%d" ,&map[i][j]);         if(!map[i][j]) map[i][j] = INF;      }      Floyd(K + C);      int Max = 0;      for(i = 1 ;i <= K ;i ++)      for(j = K + 1 ;j <= K + C ;j ++)      if(Max < map[i][j])Max = map[i][j];      int low = 0 ,up = Max ,mid ,ans;      while(low <= up)      {         mid = (low + up) >> 1;         if(ok(mid ,K ,C ,M))         {            up = mid - 1;            ans = mid;         }         else low = mid + 1;      }      printf("%d\n" ,ans);   }   return 0;}      


0 0
原创粉丝点击