• 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;
    }
    
  • 相关阅读:
    给linux用户分配docker权限
    alpine安装docker
    linux开机自启动配置
    virtualbox vdi硬盘扩容
    树莓派更新软件源的脚本
    原生js选中下拉框中指定值
    linux环境tomcat开启远程调试
    Vue2 和 Yii2 进行前后端分离开发学习
    httpd.conf文件中找不到Deny from all这句,怎么配置多站点
    yii2.0 advanced 学习教程
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9817998.html
Copyright © 2020-2023  润新知