• 2013校队选拔——最短路——二分最大边的最小值


    1012: City Tour

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 63  Solved: 11
    [Submit][Status][Web Board]

    Description

    Alice想要从城市A出发到城市B,由于Alice最近比较穷(不像集训队陈兴老师是个rich second),所以只能选择做火车从A到B。不过Alice很讨厌坐火车,火车上人比较多,比较拥挤,所以Alice有很严格的要求:火车的相邻两站间的最大距离尽可能的短,这样Alice就可以在停站的时候下车休息一下。当然Alice希望整个旅途比较短。

    Input

    有多组测试数据。
    每组测试数据的第一行有两个整数N,M,A,B(N<=1000, M<=50000, N >=2, A,B<=N),其中N是城市的个数,M是城市间通火车的个数。
    A,B是Alice起始的城市与目的地城市,城市的标号从1开始。
    接下来的M行每行三个整数u,v,w表示从u到v和从v到u有一条铁路,距离为w, u,v<=N, w<=10000。

    Output

    对于每组测试数据输出满足Alice要求的从A到B的最短距离。

    Sample Input

    3 3 1 2
    1 2 80
    1 3 40
    2 3 50
    3 3 1 2
    1 2 90
    1 3 10
    2 3 20
    4 5 1 4
    1 2 8
    1 4 9
    1 3 10
    2 4 7
    3 4 8

    Sample Output

    90
    30
    15
     
     
    又是一年校队选拔,又坑在了二分这个题目上面。
    这个题目最短路部分不难
    关键是想到用二分
    之前思路很混乱,我一度也在想要记录每条路的最大边权值,然后对求出来的最短路,优先选择最大边权值最小的那条。。。但是这种思路首先没有落实到二分这个方法上来,其次,我是想边求最短路的时候,边比较此时的最大边权,然后取小的。。非常混乱
    记得上次显神就给我讲过最大值最小化问题,我竟然没有转化到这个最短路的题目来
    题目条件要使得两个站之间的距离越短越好。。。因此是在站与站的距离越的情况下,来进行最短路。
    因此,用二分枚举出最大边权值,(意思就是在该最大权值下,如果边权值大于它,则相当于不通),在枚举出的权值下,进行朴素的迪杰斯特拉最短路(安神用的SPFA,看起来很简洁。膜拜一下。)!
    最后坑爹的二分调试了我几个小时(比赛之后)。发现二分真的不是那么好写。。尤其是这道题目,枚举出来的量稍有差池,就输不出正确的值来。
    其实后来看了下浙西贫农的代码,忽然觉悟了,不是我的二分没写好,是在判断的时候,应该在边值可达的时候记录下此时的b点最短路值,否则总会发现输出inf
    还得练习一下分治专题。
     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    #define inf 10000000
    using namespace std;
    int d[1005][1005];
    int city[1005];
    bool vis[1005];
    int n,m,a,b;
    int main()
    {
        while (scanf("%d %d %d %d",&n,&m,&a,&b)!=EOF)
        {
            int i,j,k;
            int mmax=0;
            int mmin=inf;
            for (i=0; i<=n; i++)
            {
                for (j=1; j<=n; j++)
                    d[i][j]=inf;
                city[i]=inf;
            }
    
            for (j=1; j<=m; j++)
            {
                int u,v,w;
                scanf("%d %d %d",&u,&v,&w);
                if (d[u][v]>w)
                    d[u][v]=d[v][u]=w;
                if (mmax<w) mmax=w;
                if (mmin>w) mmin=w;
            }
            city[a]=0;
            int ans=0;
            int l=mmin,r=mmax,mid;
            while (l<r) //二分部分。
            {
    
                memset(vis,0,sizeof vis);
                mid=(l+r)/2;
                for (int i2=1;i2<=n;i2++)//每次二分都要重置最短路
                {
                  city[i2]=inf;
                }
                city[a]=0;
                for (i=1;i<=n;i++)//进行朴素的Dijstla
                {
                    int min=inf,loc;
                    for (j=1;j<=n;j++)
                    {
                        if (vis[j]) continue;
                        if (min>city[j])
                        {
                            min=city[j];
                            loc=j;
                        }
                    }
                    vis[loc]=1;
                    for (k=1;k<=n;k++)
                    {
                       if (d[loc][k]>mid) continue;
                       if(vis[k]) continue;
                       if (city[k]>city[loc]+d[loc][k])
                        city[k]=city[loc]+d[loc][k];
    
                    }
                }
                if (city[b]>=inf) l=mid+1;
                else
    {
    ans=city[b];//应该在这里记录好结果。。。否则下一次二分如果是满足上面那个条件,则最终不是会输出inf r=mid;
    } } printf(
    "%d ",ans); } return 0; }
  • 相关阅读:
    排序算法的体验游戏
    【转】[Java] HashMap使用的示例
    【转】【Android】使用BaseAdapter实现复杂的ListView
    【转】Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例
    【转】Java集合框架List,Map,Set等全面介绍
    【转】java参数传递(超经典)
    bluetooth记录
    【转】Java 字符串常用操作(String类)
    【转】Java中字符串中子串的查找共有四种方法(indexof())
    【转】BLE 学习记录
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3275263.html
Copyright © 2020-2023  润新知