现在的位置: 首页 > 综合 > 正文

POJ2455 Secret Milking Machine(二分上线构图求最大流)

2013年09月21日 ⁄ 综合 ⁄ 共 1594字 ⁄ 字号 评论关闭

一张无向图中有 N 个点,M 条边,每条边都有一个权值,且每条边只能用一次,要求找出 T 条从 1 到 N 的路径,使这 T 条路径所经过的边中,权值的最大值最小。

思想:二分边权值上线,多次构图求最大流,判断max_flow是否满足 T 。详见代码:

#include<cstdio>
#include<cstring>
#include<queue>
#define find_min(a,b) a<b?a:b
#define find_max(a,b) a>b?a:b

using namespace std;

const int N = 210;
const int MAX = (int)10e7;

struct Edge{
	int s,e,v,next;
}edge[2*N*N],mat[N*N];

int e_num,head[N],d[N],sp,tp;
int n,m;

void AddEdge(int a,int b,int c){
	edge[e_num].s=a; edge[e_num].e=b; edge[e_num].v=c;
	edge[e_num].next=head[a]; head[a]=e_num++;

	edge[e_num].s=b; edge[e_num].e=a; edge[e_num].v=c;
	edge[e_num].next=head[b]; head[b]=e_num++;
}

int bfs(){
	queue <int> q;
	memset(d,-1,sizeof(d));
	d[sp]=0;
	q.push(sp);
	while(!q.empty()){
		int cur=q.front();
		q.pop();
		for(int i=head[cur];i!=-1;i=edge[i].next){
			int u=edge[i].e;
			if(d[u]==-1 && edge[i].v>0){
				d[u]=d[cur]+1;
				q.push(u);
			}
		}
	}
	return d[tp] != -1;
}

int dfs(int a,int b){
	int r=0;
	if(a==tp)return b;
	for(int i=head[a];i!=-1 && r<b;i=edge[i].next){
		int u=edge[i].e;
		if(edge[i].v>0 && d[u]==d[a]+1){
			int x=find_min(edge[i].v,b-r);
			x=dfs(u,x);
			r+=x;
			edge[i].v-=x;
			edge[i^1].v+=x;
		}
	}
	if(!r)d[a]=-2;
	return r;
}

int dinic(int sp,int tp){
	int total=0,t;
	while(bfs()){
		while(t=dfs(sp,MAX))
		total+=t;
	}
	return total;
}

void init(int index){
    int i,j;
    e_num=0;
    memset(head,-1,sizeof(head));
    for(i=1;i<=m;i++){
        if(mat[i].v<=index)AddEdge(mat[i].s,mat[i].e,1);
    }
}

int main()
{
    int t_num,i,j,a,b,c;
    while(~scanf("%d%d%d",&n,&m,&t_num)){
        sp=1;tp=n;
        int high=-1,low=MAX;
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&a,&b,&c);
            high=find_max(high,c);
            low=find_min(low,c);
            mat[i].s=a; mat[i].e=b; mat[i].v=c;
        }
        int mid,ans;
        while(low<=high){
            mid=(low+high)/2;
            init(mid);
            ans=dinic(sp,tp);
            if(ans<t_num)low=mid+1;
            else high=mid-1;
        }
        printf("%d\n",low);
    }
    return 0;
}

抱歉!评论已关闭.