• [洛谷P1401] 城市


    题目描述

    N(2<=n<=200)个城市,M(1<=m<=40000)条无向边,你要找T(1<=T<=200)条从城市1到城市N的路,使得最长的边的长度最小,边不能重复用。

    输入输出格式

    输入格式:

    第1行三个整数N,M,T用空格隔开。

    第2行到P+1行,每行包括三个整数Ai,Bi,Li表示城市Ai到城市Bi之间有一条长度为Li的道路。

    输出格式:

    输出只有一行,包含一个整数,即经过的这些道路中最长的路的最小长度。

    输入输出样例

    输入样例#1:

    7 9 2
    1 2 2
    2 3 5
    3 7 5
    1 4 1
    4 3 1
    4 5 7
    5 7 1
    1 6 3
    6 7 3

    输出样例#1:

    5

    Solution

    二分答案+网络流....
    本来想用k长路做,然后发现每条边只能经过1次

    那么,不就是网络流吗,容量为1,表示做多可以跑一次

    那么具体实现,二分一个边权,只有当小于等于这个边权的才能跑,容量为1,反向边容量为0

    因为是无向边,所以每次本来应该是4条边的,但跑的是最大流,所以容量为0的两条边就可以省略了,二分判断合法的方式就是看当前最大流能不能跑满T,T为题目输入

    Code

    #include<bits/stdc++.h>
    #define lol long long
    #define Min(a,b) (a)<(b)?(a):(b)
    #define Max(a,b) (a)>(b)?(a):(b)
     
    using namespace std;
    
    const int N=210,M=4e4+10;
    const int inf=2e9;
    
    void in(int &ans)
    {
        ans=0;int f=1; char i=getchar();
        while(i<'0'||i>'9'){if(i=='-') f=-1; i=getchar();}
        while(i>='0'&&i<='9') ans=(ans<<3)+(ans<<1)+i-'0',i=getchar();
        ans*=f;
    }
    
    int n,m,T,cur=-1;
    int l=inf,r=-inf;
    int a[M],b[M],c[M];
    int to[M<<1],head[N],nex[M<<1],vis[M<<1],cap[M<<1];
    int lev[N];
    
    inline void add(int a,int b,int c)
    {
        to[++cur]=b,nex[cur]=head[a];
        cap[cur]=c,head[a]=cur;
    }
    
    bool bfs(int s,int t)
    {
        queue<int>q;
        memset(lev,-1,sizeof(lev));
        q.push(s); lev[s]=0;
        while(!q.empty()) {
    		int u=q.front(); q.pop();
    		for(int i=head[u];i;i=nex[i]) {
    		    if(lev[to[i]]==-1 && cap[i]) {
    				lev[to[i]]=lev[u]+1; q.push(to[i]);
    		   }
    		}
        }
        return lev[t]!=-1;
    }
    
    int dfs(int s,int f,int t,int rest=0)
    {
        if(s==t) return f;
        for(int i=head[s];i;i=nex[i]) {
    		if(lev[to[i]]==lev[s]+1 && cap[i]) {
    		    int r=dfs(to[i],Min(cap[i],f-rest),t);
    		    if(r>0) {
    				rest+=r;
    				cap[i]-=r,cap[i^1]+=r;
    		    }
    		}
        }
        if(!rest) lev[s]=-1;
        return rest;
    }
    
    bool check(int mid,int ans=0)
    {
        memset(head,0,sizeof(head)); cur=-1;
        for(int i=1;i<=m;i++) {
    		if(c[i]<=mid) add(a[i],b[i],1),add(b[i],a[i],1);
        }
        while(bfs(1,n))
    		while(int c=dfs(1,inf,n)) ans+=c;
        return ans>=T;
    }
    
    int main()
    {
        in(n),in(m),in(T);
        for(int i=1;i<=m;i++) {
    		in(a[i]),in(b[i]),in(c[i]);
    		l=Min(l,c[i]),r=Max(r,c[i]);
        }
        while(l<r) {
    		int mid=l+r>>1;
    		if(check(mid)) r=mid;
    		else l=mid+1;
        }
        printf("%d
    ",r);
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    POJ 1811 大整数素数判断 Miller_Rabin
    hdu 4940 无源汇有上下界最大流
    hdu 4975 最大流解决行列和求矩阵问题,用到矩阵dp优化
    hdu 4971 多校10最大权闭合图
    hdu 4888 最大流给出行列和求矩阵
    poj 3621最优比例生成环(01分数规划问题)
    poj 2728 最优比例生成树(01分数规划)模板
    最优比例生成树最优比率生成树 01分数规划问题
    poj 2553强连通+缩点
    poj 2831 次小生成树模板
  • 原文地址:https://www.cnblogs.com/real-l/p/9583293.html
Copyright © 2020-2023  润新知