zoukankan      html  css  js  c++  java
  • UVALive

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2224

    题意:有n个城市,m条路,每条路是双向的,从一个城市到另一个城市,并且有限制通行高度,有路程。

    现在有一辆货车,有一个最高货物高度,要从一个城市到一个城市。要保证最高高度情况下,选最短路。

    思路:我们可以知道最高高度一定是1到货车高度。所以我们可以二分高度,寻找最高高度,再有dijkstra求最短路。

    但是用邻接矩阵会超时,这里可以稍稍剪枝下。怎么剪呢?只要在dijkstra算法里判断达到所求终点,或者没有路走了就退出,不用在多算。

    还有一个坑点是输出格式:第一个样例不空行输出答案,而后面要空行再输出答案。而且格式错了居然是 WA!!!

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    struct node{
        int v,h;
    }map[1050][1050];
    int n,m,high,maxh,from,to,ansh,ansv,flag;
    int dis[1050],vis[1050];
    
    void dijktra(int x)
    {
        memset(vis,0,sizeof(vis));
        vis[from]=1;
        for(int i=1;i<=n;i++)//不达到高度x的路相当于不通,赋inf即可 
        { 
            if(map[from][i].h>=x)
                dis[i]=map[from][i].v;
            else
                dis[i]=inf;    
        } 
        for(int i=1;i<n;i++)//dijkstra模板 
        {
            int t=inf,p=-1;
            for(int j=1;j<=n;j++)
            { 
                
                if(!vis[j]&&dis[j]<t)
                {
                    t=dis[j];
                    p=j;
                }
            } 
            vis[p]=1;
            if(p==to||p==-1)//剪枝 
                return ; 
            for(int j=1;j<=n;j++)
            {
                if(!vis[j]&&dis[j]>map[p][j].v+dis[p]&&map[p][j].h>=x)
                    dis[j]=map[p][j].v+dis[p];
            }
        }
    }
    void solve()//二分求高度 
    {
        int l=1,r=high;
        while(l<=r)
        {
            int mid=(l+r)/2;
            dijktra(mid);
            if(dis[to]!=inf)//mid高度有最短路 
            {
                flag=1;
                ansh=mid;
                ansv=dis[to];
                l=mid+1;
            }
            else
                r=mid-1;
        }
        return ;
    }
    int main()
    {
        int k=1;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            flag=0;
            for(int i=1;i<=n;i++)//初始化 
            {
                for(int j=1;j<=n;j++)
                {
                    map[i][j].h=0;
                    map[i][j].v=inf;
                }
            }
            if(!n&&!m)
                break;
            int u,v,g,w;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%d%d",&u,&v,&g,&w);
                if(g==-1)    g=inf;//-1为不限高度 
                map[u][v].v=map[v][u].v=w;
                map[u][v].h=map[v][u].h=g;
            }
            scanf("%d%d%d",&from,&to,&high);
            solve();
            if(k>1)
                printf("
    ");
            printf("Case %d:
    ",k++);
            if(flag)
            {
                printf("maximum height = %d
    ",ansh);
                printf("length of shortest route = %d
    ",ansv);
            }
            else
                printf("cannot reach destination
    ");
        }
        return 0;
    }
  • 相关阅读:
    整理牙刷
    color 圆盘染色
    数论の一波流[长期更新]
    生成树
    一维黑白棋
    Factorials
    平面分割问题
    poj1183 反正切函数
    烽火传递
    校门外的树
  • 原文地址:https://www.cnblogs.com/xiongtao/p/9441572.html
Copyright © 2011-2022 走看看