齐头并进(51Nod-1649)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/89522708

题目

在一个叫奥斯汀的城市,有n个小镇(从1到n编号),这些小镇通过m条双向火车铁轨相连。当然某些小镇之间也有公路相连。为了保证每两个小镇之间的人可以方便的相互访问,市长就在那些没有铁轨直接相连的小镇之间建造了公路。在两个直接通过公路或者铁路相连的小镇之间移动,要花费一个小时的时间。

现在有一辆火车和一辆汽车同时从小镇1出发。他们都要前往小镇n,但是他们中途不能同时停在同一个小镇(但是可以同时停在小镇n)。火车只能走铁路,汽车只能走公路。

现在请来为火车和汽车分别设计一条线路;所有的公路或者铁路可以被多次使用。使得火车和汽车尽可能快的到达小镇n。即要求他们中最后到达小镇n的时间要最短。输出这个最短时间。(最后火车和汽车可以同时到达小镇n,也可以先后到达。)

输入

单组测试数据。
第一行有两个整数n 和 m (2≤n≤400, 0≤m≤n*(n-1)/2) ,表示小镇的数目和铁轨的数目。
接下来m行,每行有两个整数u 和 v,表示u和v之间有一条铁路。(1≤u,v≤n, u≠v)。
输入中保证两个小镇之间最多有一条铁路直接相连。

输出

输出一个整数,表示答案,如果没有合法的路线规划,输出-1。

输入样例

4 2
1 3
3 4

输出样例

2

思路:两遍 Dijkstra 求两次的最大值即可

源程序

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 1000+5;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
using namespace std;


int n,m;
struct Edge { //边
    int from;//下一条边的编号
    int to;//边到达的点
    int dis;//边的长度
    Edge(int f,int t,int d) { //构造函数
        from=f;
        to=t;
        dis=d;
    }
};

struct HeapNode { //Dijkstra用到的优先队列的结点
    int dis;//点到起点距离
    int u;//点的序号
    HeapNode(int a,int b) {
        dis=a;
        u=b;
    }
    bool operator < (const HeapNode &rhs) const  {
        return dis > rhs.dis;
    }
};

struct Dijkstra {
    int n,m;//点数、边数,均从0开始
    vector<Edge> edges;//边列表
    vector<int> G[N];//每个结点出发的边的编号
    bool vis[N];//是否走过
    int dis[N];//起点s到各点的距离
    int p[N];//从起点s到i的最短路中的最后一条边的编号

    void init(int n) {//初始化
        this->n = n;
        for(int i=0; i<n; i++) //清空邻接表
            G[i].clear();
        edges.clear();//清空边列表
    }

    void AddEdge(int from,int to,int diss) {//添加边,若为无向图,调用两次
        edges.push_back(Edge(from,to,diss));
        m=edges.size();//边的个数
        G[from].push_back(m-1);//添加至边列表
    }

    int dijkstra(int s) {//求s到所有点的距离

        memset(dis,INF,sizeof(dis));
        memset(vis,false,sizeof(vis));
        dis[s]=0;

        priority_queue<HeapNode> Q;//优先队列
        Q.push(HeapNode(0,s));
        while(!Q.empty()) {
            HeapNode x=Q.top();
            Q.pop();

            int u=x.u;
            if(vis[u])//若已被访问
                continue;

            vis[u]=true;//标记为已访问
            for(int i=0; i<G[u].size(); i++) { //枚举所有与当前点相连的边
                Edge &e=edges[G[u][i]];
                if(dis[e.to] > dis[u]+e.dis) {//更新距离
                    dis[e.to] = dis[u]+e.dis;
                    p[e.to]=G[u][i];
                    Q.push(HeapNode(dis[e.to],e.to));
                }
            }
        }
        return dis[n];
    }
} DJ;
int mp[N][N];
int main() {
    scanf("%d%d",&n,&m);

    DJ.init(n);//初始化
    for(int i=0; i<m; i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        mp[x][y]=1;
        mp[y][x]=1;
        //无向图添边两次
        DJ.AddEdge(x,y,1);
        DJ.AddEdge(y,x,1);
    }

    int res=DJ.dijkstra(1);
    if(res==INF||m==(n*(n-1))/2)
        printf("-1\n");
    else{
        DJ.init(n);
        for(int i=1;i<=n;++i){
            mp[i][i]=1;
            for(int j=1;j<=n;++j){
                if(!mp[i][j]){
                    DJ.AddEdge(i,j,1);
                    DJ.AddEdge(j,i,1);
                }
            }
        }
        if(DJ.dijkstra(1)==INF)
            printf("-1\n");
        else{
            res=max(res,DJ.dijkstra(1));
            printf("%d\n",res);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/89522708
今日推荐