misschuer

常用链接

统计

积分与排名

百事通

最新评论

poj 2455 Secret Milking Machine

//题意是求起点到终点,满足走K次不重复的路(任何一段都不能相同),最大边中的值最小
/*
*
*6 5 1
*1 2 1
*2 3 4
*3 6 5
*1 4 1
*4 5 1
*5 6 6

从1到6有 2条路径 1-2-3-6  最大边值为 5
                 1-4-5-6  最大边值为 6

因为只走一条 所以最大边值的最小为5
若走2条        则最大边值的最小为6

具体做法:
先分别构建源点与汇点 源点为s = 0, 汇点为t = n + 1, 因为要满足走K次所以 分别连接s-1,n-t流量都为K.二分枚举最大边的值.
先left = 0, right = 1000000;(right 可以是大于等于[and with a positive length that does not exceed 1,000,000.]要求的值)
mid = (left + right) >> 1; 如果某条边(u,v)的值满足<=mid,则连接u,v, 流为1.最大流的结果若是<K说明mid不是所求的值,要增大这个值
left = mid + 1;如果最大流为K说明mid可以满足但是还要确定是否有比他小的数使得流也为K,所以right = mid - 1.二分搜完最后结果就是left

若说错了 求指教~~
*
*/
#include 
<cstdio>
#include 
<iostream>
#include 
<cstring>
using namespace std;
const int MAXV = 410;
const int MAXE = 200010;
const int inf = 1 << 29;

int head[MAXV], N;

struct Edge {

    
int v, next, w;
}edge[MAXE], tmp[MAXE];

int n, m, s, t, cnt, ans;

void add(int u, int v, int w) {

    edge[cnt].v 
= v;
    edge[cnt].w 
= w;
    edge[cnt].next 
= head[ u ];
    head[ u ] 
= cnt++;

    edge[cnt].v 
= u;
    edge[cnt].w 
= w;
    edge[cnt].next 
= head[ v ];
    head[ v ] 
= cnt++;
}

int sap() {

    
int pre[MAXV], cur[MAXV], dis[MAXV], gap[MAXV];
    
int flow = 0, aug = inf, u;
    
bool flag;

    
for(int i = 0; i <= N; ++ i) {

        cur[ i ] 
= head[ i ];
        gap[ i ] 
= dis[ i ] = 0;
    }

    gap[ s ] 
= N;
    u 
= pre[ s ] = s;

    
while(dis[ s ] < N) {

        flag 
= 0;

        
for(int &= cur[ u ]; j != -1; j = edge[ j ].next) {

            
int v = edge[ j ].v;

            
if(edge[ j ].w > 0 && dis[ u ] == dis[ v ] + 1) {

                flag 
= 1;

                
if(edge[ j ].w < aug) aug = edge[ j ].w;

                pre[ v ] 
= u;
                u 
= v;

                
if(u == t) {

                    flow 
+= aug;

                    
while(u != s) {

                        u 
= pre[ u ];
                        edge[cur[ u ]  ].w 
-= aug;
                        edge[cur[ u ]
^1].w += aug;
                    }
                    aug 
= inf;
                }
                
break;
            }
        }

        
if(flag) continue;

        
int mindis = N;

        
for(int k = head[ u ]; k != -1; k = edge[ k ].next) {

            
int v = edge[ k ].v;

            
if(edge[ k ].w > 0 && dis[ v ] < mindis) {

              mindis 
= dis[ v ];
              cur[ u ] 
= k;
            }
        }

        
if( (--gap[dis[ u ]]) == 0break;

        dis[ u ] 
= mindis + 1;
        gap[dis[ u ]] 
++;
        u 
= pre[ u ];
    }
    
return flow;
}


int main() {

    
int i, j;
    
int mm;

    
while(~scanf("%d %d %d"&m, &n, &mm)) {

        
for(i = 0; i < n; ++ i) {
        
            scanf(
"%d %d %d"&tmp[ i ].v, &tmp[ i ].next, &tmp[ i ].w);
        }


        
int left = 0, right = 1000000, mid;

        
while(left <= right) {
        
            mid 
= (left + right) >> 1;
            cnt 
= 0; s = 0; t = m - 1; N = t + 1;
            memset(head,
-1,sizeof(head));

            
for(i = 0; i < n; ++ i) {
            
                
if(tmp[ i ].w <= mid) {
                
                    add(tmp[ i ].v 
- 1, tmp[ i ].next - 11);
                }
            }


            ans 
= sap();

            
if(ans >= mm) {
            
                right 
= mid - 1
            }
            
else {
            
                left 
= mid + 1;
            }
        }
  
        printf(
"%d\n", left);
    }
    
return 0;
}

posted on 2011-03-24 11:37 此最相思 阅读(164) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理