题目
在一个叫奥斯汀的城市,有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;
}