题目大意:给你n个城市,m条道路,以及A城市与B城市之间隧道的限高,让你求最小路径。

思路:二分枚举所有的高度,然后通过Dijkstra算法求得最小的路径值。

难点:

(1)建图时有点麻烦。

(2)枚举是判断的条件与Dijkstra中的判断的条件有点麻烦。

这道题我样例全过了,但是还是WA,找不到BUG,等我学了SPFA与用邻接表建图时再来看看。)

 (现在知道原因了,我二分查找悲剧的写错了,由于最后的mid不一定满足条件,所以需要用一个h来保存。) 

 放这提醒自己。

WA CODE:

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

const int SIZE = 2020;
const int INF = 0x3f3f3f3f;
int w[SIZE][SIZE][2];
int d[SIZE], v[SIZE];
int path[SIZE];
int n, m;



int Dijkstra(int s, int e, int mid)
{
    int i;
    memset(v, 0sizeof(v));
    for(i = 1; i <= n; i++) d[i] = (i == s)? 0:INF;
    for(i = 1; i <= n; i++) path[i] = s;
    for(i = 1; i <= n; i++)
    {
        int x, m = INF;
        for(int y = 1; y <= n; y++)    if(!v[y] && m > d[y] && w[path[y]][y][0] >= mid) m = d[x=y];
        if(x == e) return 1;
        if(m == INF) return 0;
        v[x] = 1;
        for(int y = 1; y <= n ; y++)
        {
            if(d[y] > (d[x] + w[x][y][1]) && w[x][y][0] >= mid)
            {
                d[y] = d[x] + w[x][y][1];
                path[y] = x;
            }
        }
    }
    return 0;
}



void init()
{
    memset(d, 0sizeof(d));
    for(int i = 1; i <= n ; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(i == j)
            {
                w[i][j][1] = 0;
                w[i][j][0] = INF;
            }
            else
            {
                w[i][j][1] = INF;
                w[i][j][0] = 0;
            }
        }
    }
    return ;
}



int main()
{
    int times = 0;
    while(scanf("%d%d", &n, &m), n, m)
    {
        init();
        for(int i = 1; i <= m; i++)
        {
            int u, v, h, cost;
            scanf("%d%d%d%d", &u, &v, &h, &cost);
            if(h != -1) w[u][v][0] = w[v][u][0] = h;
            else w[u][v][0] = w[v][u][0] = INF;
            w[u][v][1] = w[v][u][1] = cost;
        }
        int s, e, y, x = 1, ans = 0;
        int mid;
        scanf("%d%d%d", &s, &e, &y);
        while(x <= y)
        {
            mid = (x+y)>>1;
            if(Dijkstra(s, e, mid))
            {
                ans = d[e];
                x = mid+1;
            }
            else y = mid-1;
        }
        if(times) printf("\n");
        printf("Case %d:\n", ++times);
        if(!y)
        {
            printf("cannot reach destination\n");
        }
        else
        {
            printf("maximum height = %d\n", mid);
            printf("length of shortest route = %d\n", ans);
        }
    }
}

 

 AC CODE:

 

 

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int SIZE = 10010;
const int INF = 0xfffffff;
int u[5*SIZE], v[5*SIZE], w[5*SIZE], next[5*SIZE], h[5*SIZE];
int first[SIZE], d[SIZE];
int n, m, cnt;
int s, e;

void read_graph(int u1, int v1, int w1, int h1)
{
    u[cnt] = u1; v[cnt] = v1; w[cnt] = w1; h[cnt] = h1;
    next[cnt] = first[u[cnt]];
    first[u[cnt]] = cnt++;
}

int spfa(int src, int mid)
{
    queue<int> q;
    bool inq[SIZE] = {0};
    for(int i = 1; i <= n; i++) d[i] = (i == src)?0:INF;
    q.push(src);
    while(!q.empty())
    {
        int x = q.front(); q.pop();
        inq[x] = 0;
        for(int e = first[x]; e!=-1; e = next[e]) if(d[v[e]] > d[x]+w[e] && mid <= h[e])
        {
            d[v[e]] = d[x] + w[e];
            if(!inq[v[e]])
            {
                inq[v[e]] = 1;
                q.push(v[e]);
            }
        }
    }
    if(d[e] == INF) return 0;
        return 1;
}

void init()
{
    memset(first, -1sizeof(first));
    cnt = 0;
}

int main()
{
    int times = 0;
    while(~scanf("%d%d", &n, &m), n, m)
    {
        init();
        while(m--)
        {
            int u1, v1, w1, h1;
            scanf("%d%d%d%d", &u1, &v1, &h1, &w1);
            if(h1 == -1) h1 = INF;
            read_graph(u1, v1, w1, h1);
            read_graph(v1, u1, w1, h1);
        }
        int x = 0, y, ans = INF, mid, h;
        scanf("%d%d%d", &s, &e, &y);
        while(x <= y)
        {
            mid = (x+y)>>1;
            if(spfa(s, mid))
            {
                x = mid+1;
                ans = d[e];
                h = mid;          //保存mid 
            }
            else y = mid-1;
        }
        if(times) printf("\n");
        printf("Case %d:\n", ++times);
        if(ans != INF)
        {
            printf("maximum height = %d\n", h);
            printf("length of shortest route = %d\n", ans);
        }
        else
        {
            printf("cannot reach destination\n");
        }
    }
}

 

posted on 2012-09-05 18:05  有间博客  阅读(222)  评论(0编辑  收藏  举报