hrbust 1339 Touring 最短路Dijkstra 邻接表

题目描述:

两个人从同一出发点去不同的地方,路的距离会造成花费的多少,所以两个人走的越短越好,并且两个人同乘一辆车可以使花费更低,给出每条路所连接的两个城市及该线路的花费以及两个人的出发点和他们各自的目的地,求他们需要的最小花费是多少

分析:

先同乘一段距离,再分开走,形走路线是一个Y形路线,找出一个点,使他到出发点以及他们各自的目的地三个地方的最短距离的和最小,这三个距离的和就是他们所需的最小距花费

这道题换了三种方法打的,第一种是邻接矩阵 乱入 优先队列,超空间,w[i][j]来储存 i 地到 j 地 的花费 ,后来发现若用邻接矩阵来储存花费,必定超时

超空间代码。。:其实那个spfa函数并不是spfa算法,名字是我乱入的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1010;
const int INF=0x1f1f1f1f;
const int INF1=1<<25-1;
int dislena[maxn];
int dislenb[maxn];
int dislenc[maxn];
int w[maxn][maxn];
bool visit[maxn];
vector<int> G[maxn];
int n,m;
int s,t;
struct HeapNode
{
   int d,u;
   bool operator<(const HeapNode & rhs)const
    {
   return d>rhs.d;
   }
};
void spfa(int s,int * dislen)
{
     int i,j;
         for(i=1; i<=n; i++)
            {
                if(i==s)
                {
                    dislen[i]=0;
                }
                else
                {
                    dislen[i]=w[s][i];
                }
            }
    priority_queue <HeapNode> Q;
    memset(visit,0,sizeof(visit));
    HeapNode tt;
    tt.d=0;
    tt.u=s;
      Q.push(tt);
    while(!Q.empty())
    {
        HeapNode x=Q.top();
        Q.pop();
        int u=x.u;
        if(visit[u])
            continue;
        visit[u]=true;
        for(i=0;i<G[u].size();i++)
        {
                   int v=G[u][i];
                    if(visit[v]==false&&dislen[v]>=dislen[u]+w[u][v])
                    {
                        dislen[v]=dislen[u]+w[u][v];
                        HeapNode t;
                        t.d=dislen[v];
                        t.u=v;
                        Q.push(t);
                       // Q.push((HeapNode){dislen[v],v});
                    }
        }
    }
}
int main()
{
    int cnt=1;
    while(scanf("%d",&n)!=EOF)
    {
        scanf("%d",&m);
        if(n==0&&m==0)
            break;
        int i,j;
       memset(w,0x1f,sizeof(w));
        for(i=0;i<=n;i++)
        {
            G[i].clear();
        }
        int c,a,b;
        scanf("%d%d%d",&c,&a,&b);
        int u,v,len;
        //cout<<"m==  "<<m<<endl;
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d",&u,&v,&len);
           if(w[u][v]>=len)
            {
                w[u][v]=len;
                w[v][u]=len;
                G[u].push_back(v);
                G[v].push_back(u);
            }
        }
        //cout<<"this is a good end"<<endl;
            spfa(c,dislenc);
            spfa(a,dislena);
            spfa(b,dislenb);
            cout<<"Scenario #"<<cnt++<<endl;
            if(dislenc[b]==INF||dislenc[a]==INF)
            {
                cout<<"Can not reah!"<<endl<<endl;
                continue;
            }
            long long  res=INF1*3;
            for(i=1;i<=n;i++)
            {
             long long k=dislena[i]+dislenb[i]+dislenc[i];
               if(k<res)
                    res=k;
            }
            cout<<res<<endl<<endl;
    }
    return 0;
}

第二种:已AC

正宗的邻接表,head[u]数组用来储存 u 这个点与其相连的边的编号,Arc数组里保存了相邻的点v和dis[u][v],以及下一个与u相邻的点v1所在的边的编号, 这样可以找到dis[u][v1],当。next_arc==-1时,点u相邻的点已经全部找完。碰到一个问题,不知道为什么,dij函数里加k变量的话就ac,不加的话就超时;

代码:

//m远小于n^2,故邻接矩阵超时,时间复杂度n^2,适用于稠密图,而当m远小于n^2时,可用于邻接表
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=20010;
const int INF=0x1f1f1f1f;
const int INF1=1<<25-1;
int dislena[5010];
int dislenb[5010];
int dislenc[5010];
bool visit[5010];
int n,m;
int s,t;
struct Str
{
    int num;
    int cost;
    Str(int a,int b):num(a),cost(b){}
    bool operator <(const  Str & res)const
    {
        return cost>res.cost;
    }
};
struct Arc
{
    int next_arc;
    int point;
    int cost;
};
Arc arc[maxn];
int head[5010];
void dij(int src,int n,int *low)
{
    memset(visit,0,sizeof(visit));
    priority_queue<Str> q;
    Str str1(src,0);
    q.push(str1);
    int k=0;
    while(k<n&&!q.empty())
    {
        Str s=q.top();
        q.pop();
        if(visit[s.num]==1)
            continue;
            visit[s.num]=1;
        low[s.num]=s.cost;
        k++;
        for(int e=head[s.num];e!=-1;e=arc[e].next_arc)
        {
            if(visit[arc[e].point]==0)
            {
                Str str2(arc[e].point,arc[e].cost+s.cost);
                q.push(str2);
            }
        }
    }
}
int main()
{
    int cnt=1;
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,-1,sizeof(head));
        memset(dislena,0x1f,sizeof(dislena));
        memset(dislenb,0x1f,sizeof(dislenb));
        memset(dislenc,0x1f,sizeof(dislenc));
        scanf("%d",&m);
        if(n==0&&m==0)
            break;
        int i,j;
        int c,a,b;
        scanf("%d%d%d",&c,&a,&b);
        int u,v,len;

        for(i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&len);
          arc[i].next_arc=head[u];
          arc[i].point=v;
          arc[i].cost=len;
          head[u]=i;

          arc[m+i].next_arc=head[v];
          arc[m+i].point=u;
          arc[m+i].cost=len;
          head[v]=m+i;
        }
           dij(c,n,dislenc);
           dij(a,n,dislena);
           dij(b,n,dislenb);
            printf("Scenario #%d\n",cnt++);
            if(dislenc[b]==INF||dislenc[a]==INF)
            {
                printf("Can not reah!\n");
                continue;
            }
            long long  res=INF1*3;
            for(i=1;i<=n;i++)
            {
             long long k=dislena[i]+dislenb[i]+dislenc[i];
               if(k<res)
                    res=k;
            }
            printf("%d\n\n",res);
    }
    return 0;
}

第三种:

用G[u][i]表示u点相连的点v在所在的边edges[G[u][i]],其实与第二种很像;

代码:已AC

//m远小于n^2,故邻接矩阵超时,时间复杂度n^2,适用于稠密图,而当m远小于n^2时,可用于邻接表
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
const int INF=0x1f1f1f1f;
const int INF1=1<<25-1;
int dislena[5010];
int dislenb[5010];
int dislenc[5010];
int n,m;
struct Edge
{
    int from;
    int to;
    int dist;
    Edge(int u,int v,int d):from(u),to(v),dist(d) {}
};
vector<Edge> edges;
vector<int > G[5010];
bool visit[5010];
void init()
{
    for(int i=0; i<=n; i++)
    {
        G[i].clear();
    }
      edges.clear();
}
void AddEdge(int from,int to,int dist)
{
    edges.push_back(Edge(from,to,dist));
    int m=edges.size();
    G[from].push_back(m-1);
}
struct HeapNode
{
    int d;
    int u;
    bool operator< (const HeapNode & rhs )const {
    return d>rhs.d;}
};
void dij(int src,int n,int *low)
{
    memset(visit,0,sizeof(visit));
    priority_queue <HeapNode> q;
    for(int i=0;i<=n;i++)
        low[i]=INF;
        low[src]=0;
      q.push((HeapNode){0,src});
      //cout<<"src== "<<src<<endl;
      int k=0;
    while(k<n&&!q.empty())
    {
        HeapNode x=q.top();
        q.pop();
        int u=x.u;
        //cout<<"u== "<<u<<endl;
        if(visit[u]==1)
            continue;
        visit[u]=1;
        k++;
        for(int i=0;i<G[u].size();i++)
        {
            Edge &e= edges[G[u][i]];
            //cout<<"e.from== "<<e.from<<endl;
            //cout<<"e.to==   "<<e.to<<endl;
            //cout<<"low[u]==    "<<low[u]<<endl;
           // cout<<"low[e.to]== "<<low[e.to]<<endl;
           // cout<<"e.dist==    "<<e.dist<<endl;
            if(visit[e.to]==0&&low[e.to]>low[u]+e.dist)
            {
                low[e.to]=low[u]+e.dist;
                q.push((HeapNode){low[e.to],e.to});
            }
        }
    }
}
int main()
{
    int cnt=1;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        scanf("%d",&m);
        if(n==0&&m==0)
            break;
        int i,j;
        int c,a,b;
        scanf("%d%d%d",&c,&a,&b);
        int u,v,len;
        for(i=1; i<=m; i++)
        {
            scanf("%d%d%d",&u,&v,&len);
            AddEdge(u,v,len);
            AddEdge(v,u,len);
        }
        //cout<<"this is one"<<endl;
        dij(c,n,dislenc);
        dij(a,n,dislena);
        dij(b,n,dislenb);
        //cout<<"this is two"<<endl;
        printf("Scenario #%d\n",cnt++);
        if(dislenc[b]==INF||dislenc[a]==INF)
        {
            printf("Can not reah!\n");
            continue;
        }
        long long  res=INF1*3;
        for(i=1; i<=n; i++)
        {
            long long k=dislena[i]+dislenb[i]+dislenc[i];
            if(k<res)
                res=k;
        }
        printf("%d\n\n",res);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-29 15:13:43

hrbust 1339 Touring 最短路Dijkstra 邻接表的相关文章

POJ3159 Dijkstra+邻接表+优先队列

今天学习到了一种新姿势,用邻接表+优先队列优化Dijkstra,这样时间复杂度就由O(N^2+E)变为O(NlogN+E),妈妈再也不用担心我超时了!~\(^o^)/ Candies Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 25077   Accepted: 6810 Description During the kindergarten days, flymouse was the monitor of his

HDU 2544 最短路 SPFA 邻接表 模板

Problem Description 在每年的校赛里,全部进入决赛的同学都会获得一件非常美丽的t-shirt.可是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以如今他们想要寻找最短的从商店到赛场的路线,你能够帮助他们吗? Input 输入包含多组数据.每组数据第一行是两个整数N.M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路.N=M=0表示输入结束.接下来M行,每行

【Dijkstra+邻接表求次短路】POJ Sightseeing 3463

Language: Default Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7766   Accepted: 2766 Description Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to

ACM:最短路,dijkstra,邻接表的建立,使用邻接表跟优先队列的dijkstra,Bellman-Ford,Floyd。。

(一)dijkstra,邻接矩阵 所有边权均为正,不管有没有环,求单个源点出发,到所有节点的最短路.该方法同时适用于有向图和无向图. #include <iostream> #include <string> #include <stack> using namespace std; const int MAXN = 1000; const int INF = 100000000; int n, m; int maze[MAXN][MAXN], vis[MAXN], d

hrbust1339 Touring (Dijkstra最短路径)(邻接表)

本文出自:http://blog.csdn.net/svitter 题意:两个人从c出发,分别想去a,b旅行,两个城市之间只有一条路,有一个相应的价值.求最小的价值.通行的时候只花费一个价值. 本题目的关键在于优先队列,求出a, b, c到各点的最小价值,然后从中挑选一个点作为分开的点. dijktra算法时用邻接表存储,因为明显是稀疏图..还有就是存边的时候记得存双向的边,利用优先队列弹出最小的花费.使用邻接表记得初始化node[i] = -1(可以用memset) AC: //=======

POJ 2387 Til the Cows Come Home dijkstra算法 用邻接表和邻接矩阵

题目如下: Til the Cows Come Home Time Limit: 1000MS        Memory Limit: 65536K Total Submissions: 27726        Accepted: 9353 Description Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wa

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

HDU 1874  畅通工程续 解题报告: 由于顶点(城镇)的数目只有200个,所以可以采用邻接矩阵的形式来存储,代码会更简洁些,也不容易出错.但是处于练习的目的,采用邻接表+优先队列的方式实现,优先队列使用STL中的priority_queue.很基础的单源单汇最短路径. HDU 2544  最短路 解题报告: 基本和1874是一样的,只是数据量小了,并且要求当n==0 && m==0时终止,值得注意!这道题同时也保证了一定是可达的,所以输出时可以直接输出. HDU 2066  一个人的

Dijkstra[两种邻接表+优先队列优化]

Dijksta算法中,如果我们采用的是邻接矩阵来存的,第一点浪费的空间比较多,第二点我们知道算法的时间复杂度在O(n*n),这样的算法可以说并不是很好,所以我们考虑优化它首先我们可以优化存储结构,采用邻接表来存储,其次我们可以用优先队列来排序大小,其时间复杂度大大降低. 需要注意的是pair是按照第一个元素的大小排序,如果相同才按照第二个,所以我们要把d[i]包装在第一个元素上. vector实现邻接表+优先队列 (假设边一开始是字符型的,这么假设是为了加点难度) #include<iostre

邻接表实现Dijkstra算法以及DFS与BFS算法

//============================================================================ // Name : ListDijkstra.cpp // Author : fffff // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //==========================