POJ 2455.Secret Milking Machine【最大流+二分】

本文介绍了解决POJ2455问题的方法,该问题涉及图论中的最大流算法结合二分查找技巧。文章详细解释了如何通过设置每条边的容量为1来确保路径的独特性,并利用二分查找确定最长边的最小值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

POJ 2455.Secret Milking Machine【最大流+二分】

分类: 【图论专辑】   292人阅读  评论(0)  收藏  举报

         这道题做了两个小时,做的我都快崩溃了。。。先是没有发现两个点之间可以有多条边,然后又忽略了是双向边,无比郁闷啊。看来读题也是一个能力啊,我太弱了。。。

         题目给出N个点和P条边,(两个点之间可能有多条边),然后问如果想要从1走到N走T次并且每条路只能走一次的话,求所走过的路中最长的边的最小值。

         我们可以用最大流来解决这个问题,首先考虑不重复的走T次,只需使每条路的容量为1就好,然后看容量能不能达到T。为了求最长边的最小值,我们可以二分最长边,先对所有边进行排序,然后每次对长度在该次二分长度之内的边容量设为1,求最大流。

        

[cpp]  view plain copy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <queue>  
  4. #include <algorithm>  
  5. #define min(a,b) ((a)<(b)?(a):(b))  
  6. #define INF 0x1f1f1f1f  
  7. #define MAXN 220  
  8. using namespace std;  
  9. int cap[MAXN][MAXN],f[MAXN][MAXN],level[MAXN],q[MAXN];  
  10. int src,sink,n,limit,m,t;  
  11. struct Edge{  
  12.     int u,v,dist;  
  13.     Edge(){}  
  14.     Edge(int _u,int _v,int _dist):u(_u),v(_v),dist(_dist){}  
  15.     bool operator<(const Edge &n)const{  
  16.         return dist < n.dist;  
  17.     }  
  18. }edge[MAXN*MAXN];  
  19. inline bool dinic_bfs(){  
  20.     int queue[MAXN];  
  21.     memset(level,-1,sizeof(level));  
  22.     int tail = 0,head = 0;  
  23.     queue[tail++] = src;  
  24.     level[src] = 0;  
  25.     while(tail > head){  
  26.         int tep = queue[head++];  
  27.         for(int i = 1;i <= n; ++i){  
  28.             if(level[i] == -1 && cap[tep][i] > f[tep][i]){  
  29.                 level[i] = level[tep] + 1;  
  30.                 queue[tail++] = i;  
  31.             }  
  32.         }  
  33.     }  
  34.     return level[sink] != -1;  
  35. }  
  36. inline int dinic(){  
  37.     int tail,cur,m,k;  
  38.     int maxflow = 0, *stack = q;  
  39.     while(dinic_bfs()){  
  40.         tail = 0;  
  41.         stack[tail++] = src;  
  42.         while(tail){  
  43.             cur = stack[tail-1];  
  44.             if(cur == sink){  
  45.                 m = INF;  
  46.                 for(int i = 1;i < tail; ++i){  
  47.                     if(m > cap[stack[i-1]][stack[i]] - f[stack[i-1]][stack[i]]){  
  48.                         m =  cap[stack[i-1]][stack[i]] - f[stack[i-1]][stack[i]];  
  49.                         k = i;  
  50.                     }  
  51.                 }  
  52.                 maxflow += m;  
  53.                 for(int i = 1;i < tail; ++i){  
  54.                     f[stack[i-1]][stack[i]] += m;  
  55.                     f[stack[i]][stack[i-1]] -= m;  
  56.                 }  
  57.                 tail = k;  
  58.             }  
  59.             else{  
  60.                 int i;  
  61.                 for(i = 1;i <= n; ++i){  
  62.                     if(level[i] == level[cur] + 1 && cap[cur][i] > f[cur][i]){  
  63.                         stack[tail++] = i;;  
  64.                         break;  
  65.                     }  
  66.                 }  
  67.                 if(i == n+1){  
  68.                     level[cur] = -1;  
  69.                     --tail;  
  70.                 }  
  71.             }  
  72.         }  
  73.     }  
  74.     return maxflow;  
  75. }  
  76. inline void rebuild(int mid){  
  77.     memset(f,0,sizeof(f));  
  78.     memset(cap,0,sizeof(cap));  
  79.     for(int i = 1;i <= mid; ++i){  
  80.         cap[edge[i].u][edge[i].v] ++;  
  81.         cap[edge[i].v][edge[i].u] ++;  
  82.     }  
  83. }  
  84. int main()  
  85. {  
  86.     int u,v,w,high,low;  
  87.     while(scanf("%d%d%d",&n,&m,&t) != EOF){   
  88.         memset(f,0,sizeof(f));  
  89.         memset(cap,0,sizeof(cap));  
  90.         src = 1; sink = n;  
  91.         for(int i = 1;i <= m; i++){  
  92.             scanf("%d%d%d",&u,&v,&w);  
  93.             edge[i] = Edge(u,v,w);  
  94.         }  
  95.         sort(edge+1,edge+m+1);  
  96.         low = 1; high = m;  
  97.         int mid,flow,ans = INF;  
  98.         while(high >= low){  
  99.             mid = (high + low)/2;  
  100.             rebuild(mid);  
  101.             flow = dinic();  
  102.             if(flow >= t){  
  103.                 high = mid - 1;  
  104.                 if(edge[mid].dist < ans) ans = edge[mid].dist;  
  105.             }  
  106.             else  low = mid + 1;  
  107.         }  
  108.         //printf("m = %d and low = %d/n",m,low);  
  109.         printf("%d/n",ans);  
  110.     }     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值