1. 程式人生 > >A類 poj2387Til the Cows Come Home

A類 poj2387Til the Cows Come Home

A類 poj2387Til the Cows Come Home

題意:

一個無向帶權圖有n個頂點,T條邊。頂點序號從1到n。求序號為1的點到序號為n的頂點的最短路。

分析:

注意是無向圖,所以要存兩次邊

這題和B類的那道相似,都用了鏈式前向星及佇列和堆,但是要注意邊和點的輸出位置換了一下

用了鏈式前向星就不用考慮重邊的問題

wa了好多次。。。。。。。。。

程式碼:

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

#define maxn 100010
#define maxm 500010
#define INF 0x7fffffff

int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn];

struct Edge{     
    int u,v,w,next;
}edge[maxm];

struct node{    //堆節點
    int w,pos;
    bool operator<(const node &x)const{
        return w>x.w;
    }
};

priority_queue<node>q;    //堆

inline void add(int u,int v,int w){        //鏈式前向星
    edge[++cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
}

void dijkstra(){
    for(int i=1;i<=n;i++){
        dis[i]=INF;
    }
    dis[1]=0;    // 賦初值 s到s的距離為0
    q.push((node){0,1});    // 把源點扔進堆裡
    while(!q.empty()){
        node x=q.top();    // 取堆頂
        q.pop();    // 彈堆
        int u=x.pos;
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].v;
            if(dis[v]>dis[u]+edge[i].w){
                dis[v]=dis[u]+edge[i].w;    // 鬆弛操作
                if(!vis[v]){
                    q.push((node){dis[v],v});
                }
                
            }
        }
    }
}

int main(){
    scanf("%d%d",&m,&n);  //注意和B類那道題的不同。。。。。。
    for(int i=1,x,y,z;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);    // 加單向邊
        add(y,x,z);   // 無向圖加兩次。。。。。。
    }
    dijkstra();
    printf("%d\n",dis[n]);
    return 0;
}