码迷,mamicode.com
首页 > 其他好文 > 详细

【HDU 1874 2544 2066 2112】 Dijkstra单源最短路径专题 —— 优先队列+邻接表/邻接矩阵

时间:2015-05-02 16:40:49      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:acm   hdu   dijkstra   优先队列   最短路径   

HDU 1874  畅通工程续


解题报告:

由于顶点(城镇)的数目只有200个,所以可以采用邻接矩阵的形式来存储,代码会更简洁些,也不容易出错。但是处于练习的目的,采用邻接表+优先队列的方式实现,优先队列使用STL中的priority_queue。很基础的单源单汇最短路径。



HDU 2544  最短路


解题报告:

基本和1874是一样的,只是数据量小了,并且要求当n==0 && m==0时终止,值得注意!这道题同时也保证了一定是可达的,所以输出时可以直接输出。



HDU 2066  一个人的旅行


解题报告:

这是一道多源多汇的最短路径问题,要新增一个统一的虚源,记为0(其实就是看成是草儿的家),并且0和其它源的距离都是0,这样就完成了转化。值得注意的是,输入数据是有重边的,如果用邻接矩阵做,要比较去重,邻接表的话,直接做就是了!




HDU 2112  HDU Today


解题报告:

看完题目直接笑喷了,能不要这么逗么!!!其实这题也就是要处理下字符串而已,直接用map映射成整数,映射完后,就跟2544和1874是一样的了。唯一值得注意的就是:start和end是可能一样的!




/// HDU 1874  邻接表+优先队列
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std; 
typedef pair<int,int> mp;

int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+10;
bool vis[maxv];
int dist[maxv];        // dist[i]表示S到i的最短距离
int parent[maxv];      // parent[i]表示S到i的最短路径中i的前一个节点
vector<mp> V[maxv]; //邻接表[i:j1,j2...]和权重w

void dijkstra(int S)
{
    //initial
    for(int i=0;i<maxv;++i) {dist[i]=INT_MAX;vis[i]=false;}
    priority_queue<mp,vector<mp>,greater<mp> > heap;
    dist[S]=0; heap.push(mp(0,S));

    while( !heap.empty() )
    {   //initial
        mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
        int u=now.second;//int uCost=now.first;
        if(vis[u]) continue;  vis[u]=true;
        

        for(int i=0;i<V[u].size();++i)
        {
            int v=V[u][i].second;
            int edgeCost=V[u][i].first;
            if(dist[u]+edgeCost < dist[v]){
                dist[v]=dist[u]+edgeCost ;
                parent[v]=u;
                heap.push(mp(dist[v],v));
            }
        } //for
    }
}
void printPath(int TT)
{
    if(parent[TT]==S)
        cout<<S<<"->"<<TT;
    else{
        printPath(parent[TT]);
        cout<<"->"<<TT;
    }
}

int main()
{
    int v1,v2,w,ans;
    while(cin>>n>>m)
    {
        for(int i=0;i<n;++i) V[i].clear();
        for(int i=0;i<m;++i)
        {
            cin>>v1>>v2>>w;
            V[v1].push_back(mp(w,v2));
            V[v2].push_back(mp(w,v1));
        }
        cin>>S>>T;

        dijkstra(S);
        ans=(dist[T]==INT_MAX?-1:dist[T]);
        cout<<ans<<endl;
    }
}


// HDU 2544 (邻接表+ 优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std;
typedef pair<int,int> mp;
struct edge{
    int next,cost;
    edge(){}
    edge(int n,int c):next(n),cost(c){}
};

int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+1;
int dist[maxv];        // dist[i]表示S到i的最短距离
int previous[maxv];      // prev[i]表示S到i的最短路径中i的前一个节点
vector<edge> V[maxv]; //邻接表[i:j1,j2...]和权重w

int dijkstra(int S,int T)
{
    //initial
    for(int i=1;i<=n;++i) dist[i]=INT_MAX; dist[S]=0;
    priority_queue<mp> heap; heap.push(mp(dist[S],S));

    while( !heap.empty() )
    {
        mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
        int nowV=now.second;int nowCost=now.first;
        //if(nowV==T) return dist[T];
        if(nowV!=S && dist[nowV]<= nowCost) continue;//由于顶点的值会更新,旧的会形成冗余
        // dist[nowV]是已经确定了的最小距离,nowCost是当前路径下nowV的距离

        for(int i=0;i<V[nowV].size();++i)
        {
            int nextV=V[nowV][i].next;
            int edgeCost=V[nowV][i].cost;
            if(nowCost+edgeCost < dist[nextV]){
                dist[nextV]=nowCost+edgeCost ;
                previous[nextV]=nowV;
                heap.push(mp(dist[nextV],nextV));
            }
        } //for
    }
    return dist[T];
}

int main()
{
    int v1,v2,w;
    while(cin>>n>>m && n+m)
    {
        for(int i=1;i<=n;++i) V[i].clear();
        for(int i=1;i<=m;++i)
        {
            cin>>v1>>v2>>w;
            V[v1].push_back(edge(v2,w));
            V[v2].push_back(edge(v1,w));
        }
        cout<<dijkstra(1,n)<<endl;
    }
}



/// HDU 2066 (邻接矩阵+优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std; //why scanf is better than cin???
typedef pair<int,int> mp;

int S,T; //Source and Terminate
const int maxv=1000+50;
bool vis[maxv];
int dist[maxv];        // dist[i]表示S到i的最短距离
int parent[maxv];      // parent[i]表示S到i的最短路径中i的前一个节点
int mat[maxv][maxv];    //邻接矩阵

void dijkstra(int source)
{
    initial
    for(int i=0;i<maxv;++i) {dist[i]=INT_MAX; vis[i]=false;}
    priority_queue<mp,vector<mp>,greater<mp> > heap;
    dist[source]=0; heap.push(mp(dist[source],source));

    while( !heap.empty() )
    {
        mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
        int u=now.second;
        if(vis[u]) continue; //可能重复push同一个u
        vis[u]=true;

        for(int v=1;v<maxv;++v)
            if(!vis[v] && mat[u][v]!=INT_MAX && dist[u]+mat[u][v] < dist[v])
            {   // relax松弛
                dist[v]=dist[u]+mat[u][v] ;
                parent[v]=u;
                heap.push(mp(dist[v],v));
            }
    }
}
void printPath(int TT)
{
    if(parent[TT]==S)
        cout<<S<<"->"<<TT;
    else{
        printPath(parent[TT]);
        cout<<"->"<<TT;
    }
}

int main()
{
    int v1,v2,w;
    int t,s,d,end[maxv]; //t条路径(可重复),d个起点,t个终点
    while(cin>>t>>s>>d)
    {
        初始化邻接矩阵
        for(int i=0;i<maxv;++i)
            for(int j=i;j<maxv;++j)
                mat[i][j]=mat[j][i]=INT_MAX;
        输入
        for(int i=1;i<=t;++i){
            cin>>v1>>v2>>w;
            if(mat[v1][v2]>w)//去重
                mat[v1][v2]=mat[v2][v1]=w;
        }
        for(int i=1;i<=s;++i){
            cin>>v2;
            mat[0][v2]=0; // 多起点,设置统一起点0
        }
        for(int i=0;i<d;++i)
            cin>>end[i]; // 多终点

        dijkstra
        dijkstra(0); int ans=INT_MAX;
        for(int i=0;i<d;++i){
            printPath(end[i]);cout<<endl;
            if(dist[end[i]]<ans) ans=dist[end[i]];
        } //输出最近终点的距离
        cout<<ans<<endl;
    }
}

/// HDU 2066 (邻接表+优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std;
typedef pair<int,int> mp;

int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+10;
bool vis[maxv];
int dist[maxv];        // dist[i]表示S到i的最短距离
int parent[maxv];      // parent[i]表示S到i的最短路径中i的前一个节点
vector<mp> V[maxv]; //邻接表[i:j1,j2...]和权重w

void dijkstra(int S)
{
    //initial
    for(int i=0;i<maxv;++i) {dist[i]=INT_MAX;vis[i]=false;}
    priority_queue<mp,vector<mp>,greater<mp> > heap;
    dist[S]=0; heap.push(mp(0,S));

    while( !heap.empty() )
    {   //initial
        mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
        int u=now.second;
        if(vis[u]) continue; vis[u]=true;
        //if(dist[u]< uCost) continue;//由于顶点的值会更新,旧的会形成冗余
        // dist[u]是已经确定了的最小距离,uCost是当前路径下u的距离

        for(int i=0;i<V[u].size();++i)
        {
            int v=V[u][i].second;
            int edgeCost=V[u][i].first;
            if(dist[u]+edgeCost < dist[v]){
                dist[v]=dist[u]+edgeCost ;
                parent[v]=u;
                heap.push(mp(dist[v],v));
            }
        } //for
    }
}
void printPath(int TT)
{
    if(parent[TT]==S)
        cout<<S<<"->"<<TT;
    else{
        printPath(parent[TT]);
        cout<<"->"<<TT;
    }
}

int main()
{
    int v1,v2,w;
    int t,s,d,end[maxv]; //t条路径(可重复),d个起点,t个终点
    while(cin>>t>>s>>d)
    {
        for(int i=0;i<maxv;++i) V[i].clear();
        //输入
        for(int i=1;i<=t;++i){
            cin>>v1>>v2>>w;
            V[v1].push_back(mp(w,v2));
            V[v2].push_back(mp(w,v1));
        }
        for(int i=1;i<=s;++i){
            cin>>v2;
            V[0].push_back(mp(0,v2)); // 多起点,设置统一起点0
        }
        for(int i=0;i<d;++i)
            cin>>end[i]; // 多终点

        dijkstra(0); int ans=INT_MAX;
        for(int i=0;i<d;++i){
            //printPath(end[i]);cout<<endl;
            if(dist[end[i]]<ans) ans=dist[end[i]];
        } //输出最近终点的距离
        cout<<ans<<endl;
    }
}




/// HDU 2112 (邻接矩阵+优先队列)
#include<iostream>
#include<string>
#include<map>
#include<queue>
#include <functional>
#include<climits>
#include<utility>
using namespace std;
typedef pair<int,int> pii;

const int maxv=150+10;
int n,t;
string start,finish,s,e;
map<string,int> mapp;
bool vis[maxv];
int dist[maxv];
//int parent[maxv];
int mat[maxv][maxv];

void dijkstra(int source)
{   // initial
    for(int i=0;i<maxv;++i){dist[i]=INT_MAX; vis[i]=false;}
    priority_queue<pii,vector<pii>,greater<pii> > heap;
    dist[source]=0;heap.push(pii(dist[source],source));

    while( !heap.empty() )
    {
        int u=heap.top().second; heap.pop();
        if(vis[u]) continue;
        vis[u]=true;

        for(int v=0;v<maxv;++v)
        if(!vis[v] && mat[u][v]!=INT_MAX && dist[u]+mat[u][v] < dist[v])
        {
            dist[v]=dist[u]+mat[u][v];
            //parent[v]=u;
            heap.push(pii(dist[v],v));
        }
    }
}

int main()
{
    while(cin>>n && n+1)
    {
        cin>>start>>finish;

        mapp.clear();
        for(int i=0;i<maxv;++i)for(int j=i+1;j<maxv;++j) mat[j][i]=mat[i][j]=INT_MAX;
        int k=0; mapp[start]=k++; mapp[finish]=k++;
        for(int i=0;i<n;++i){
            cin>>s>>e>>t;
            if(!mapp.count(s)) mapp[s]=k++;
            if(!mapp.count(e)) mapp[e]=k++;
            if(t < mat[mapp[s]][mapp[e]])
                mat[mapp[e]][mapp[s]]=mat[mapp[s]][mapp[e]]=t;
        }

        //if(start==finish){cout<<0<<endl;continue;}
        //if(n==0){cout<<-1<<endl;continue;}
        dijkstra(mapp[start]);
        cout<<(dist[mapp[finish]]==INT_MAX?-1:dist[mapp[finish]])<<endl;
    }
    return 0;
}




写在最后:

HDU 2680  Choose the best route

HDU 1385 Minimum Transport Cost

HDU 1548 A strange lift





【HDU 1874 2544 2066 2112】 Dijkstra单源最短路径专题 —— 优先队列+邻接表/邻接矩阵

标签:acm   hdu   dijkstra   优先队列   最短路径   

原文地址:http://blog.csdn.net/treasuresss/article/details/45439813

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!