HDU 4479 Shortest path 带限制最短路

题意:给定一个图,求从1到N的递增边权的最短路。

解法:类似于bellman-ford思想,将所有的边先按照权值排一个序,然后依次将边加入进去更新,
每条边只更新一次,为了保证得到的路径是边权递增的,每次将相同权值的边全部取出来一同更新,
每条边能够更新的前提是某一个端点在之前被更小的边权更新过。另外一个要注意的地方就是一次相同边的更新中,
要把所有的更新暂存起来最后一起去更新,这样是为了防止同一权值的边被多次加入到路径中去。

#include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const LL maxn = 10005;
const LL maxm = 50005;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
struct node{
    int u,v,len;
    bool operator < (node a)const{
        return len < a.len;
    }
}edge[maxm];
LL dis[maxn];
int id,n,m;

struct Rec{
    int v;
    LL d;
}rec[maxn];
void update(int l,int r){
    int index = 0;
    for(int i = l; i <= r; i++){
        int u = edge[i].u,v = edge[i].v,len = edge[i].len;
        if( dis[u] != INF && dis[v] > dis[u] + len )
        rec[index].v  = v,rec[index++].d = dis[u] + len;
        if( dis[v] != INF && dis[u] > dis[v] + len)
        rec[index].v = u,rec[index++].d = dis[v] + len;
    }
    for(int i = 0; i < index; i++)
    dis[rec[i].v] = min(dis[rec[i].v],rec[i].d);
}
void slove(){
    memset(dis,0x3f,sizeof(dis));
    cout << dis[0] << endl;
    dis[1] = 0;
    for(int i = 0,j; i < m; i = j){
        for( j = i+1; j < m ;j ++)
        if( edge[i].len != edge[j].len)
        break;
        update(i,j-1);
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while( t-- ){
        scanf("%d%d",&n,&m);
        for(int i = 0; i < m; i++)
        scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].len);
        sort(edge,edge+m);
        slove();
        if( dis[n] == INF)puts("No answer");
        else printf("%I64d\n",dis[n]);
    }
    return 0;
}

 

posted @ 2013-08-27 20:18  一生挚爱  阅读(368)  评论(0编辑  收藏  举报