zoukankan      html  css  js  c++  java
  • Luogu P1401 城市(二分+网络流)

    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
    

    思路

    这道题可以用并查集做。 --alecli

    每条边最多走一遍,不就相当于对图跑一遍网络流,流量必须大于等于(T)吗?所以我们可以二分答案,对原图跑网络流,判断流量是否满足要求。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,t,ans,L=INT_MAX,R,cur[205],dep[205];
    int cnt=1,top[205],to[160005],len[160005],cap[160005],rcap[160005],nex[160005];
    int read()
    {
        int re=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    bool bfs(int lim)
    {
        memset(cur,0,sizeof cur);
        memset(dep,0,sizeof dep);
        cur[1]=top[1],dep[1]=1;
        queue<int>Q;
        Q.push(1);
        while(!Q.empty())
        {
            int now=Q.front();Q.pop();
            for(int i=cur[now];i;i=nex[i])
                if(!dep[to[i]]&&len[i]<=lim&&cap[i])
                {
                    cur[to[i]]=top[to[i]],dep[to[i]]=dep[now]+1;
                    Q.push(to[i]);
                }
        }
        return dep[n]!=0;
    }
    int dfs(int now,int flow,int lim)
    {
        if(now==n) return flow;
        int re=0;
        for(int &i=cur[now];i;i=nex[i])
            if(dep[to[i]]==dep[now]+1&&len[i]<=lim&&cap[i])
            {
                int lzq=dfs(to[i],min(flow,cap[i]),lim);
                if(lzq)
                {
                    re+=lzq,flow-=lzq;
                    cap[i]-=lzq,cap[i^1]+=lzq;
                    if(!flow) break;
                }
            }
        return re;
    }
    bool check(int lim)
    {
        int tmp=0;
        for(int i=1;i<=cnt;i++) cap[i]=rcap[i];
        while(bfs(lim)) tmp+=dfs(1,INT_MAX,lim);
        return tmp>=t;
    }
    int main()
    {
        n=read(),m=read(),t=read();
        while(m--)
        {
            int x=read(),y=read(),z=read();
            to[++cnt]=y,len[cnt]=z,cap[cnt]=rcap[cnt]=1,nex[cnt]=top[x],top[x]=cnt;
            to[++cnt]=x,len[cnt]=z,cap[cnt]=rcap[cnt]=0,nex[cnt]=top[y],top[y]=cnt;
            to[++cnt]=y,len[cnt]=z,cap[cnt]=rcap[cnt]=0,nex[cnt]=top[x],top[x]=cnt;
            to[++cnt]=x,len[cnt]=z,cap[cnt]=rcap[cnt]=1,nex[cnt]=top[y],top[y]=cnt;
            L=min(L,z),R=max(R,z);
        }
        while(L<=R)
        {
            int mid=(L+R)>>1;
            if(check(mid)) ans=mid,R=mid-1;
            else L=mid+1;
        }
        printf("%d",ans);
        return 0;
    }
    
  • 相关阅读:
    C/C++中变量的作用域和存储类型简介
    Java与JavaScript的区别你明白吗?
    js-2018-11-09 关于Array中的srot()方法和compare()方法
    js-2018-11-01 关于break和continue语句
    0427表格学习
    0426基础标签学习
    css3部分整理
    img图片占不满整个div
    基于google protobuf 的 socket udp 通信
    微信小程序echarts学习记录
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9817998.html
Copyright © 2011-2022 走看看