Two Paths
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 190 Accepted Submission(s): 113
Problem Description
You are given a undirected graph with n nodes (numbered from 1 to n) and m edges. Alice and Bob are now trying to play a game.
Both of them will take different route from 1 to n (not necessary simple).
Alice always moves first and she is so clever that take one of the shortest path from 1 to n.
Now is the Bob’s turn. Help Bob to take possible shortest route from 1 to n.
There’s neither multiple edges nor self-loops.
Two paths S and T are considered different if and only if there is an integer i, so that the i-th edge of S is not the same as the i-th edge of T or one of them doesn’t exist.
Input
The first line of input contains an integer T(1 <= T <= 15), the number of test cases.
The first line of each test case contains 2 integers n, m (2 <= n, m <= 100000), number of nodes and number of edges. Each of the next m lines contains 3 integers a, b, w (1 <= a, b <= n, 1 <= w <= 1000000000), this means that there’s an edge between node a and node b and its length is w.
It is guaranteed that there is at least one path from 1 to n.
Sum of n over all test cases is less than 250000 and sum of m over all test cases is less than 350000.
Output
For each test case print length of valid shortest path in one line.
Sample Input
2
3 3
1 2 1
2 3 4
1 3 3
2 1
1 2 1
Sample Output
5
3
Hint
For testcase 1, Alice take path 1 - 3 and its length is 3, and then Bob will take path 1 - 2 - 3 and its length is 5.
For testcase 2, Bob will take route 1 - 2 - 1 - 2 and its length is 3
Source
2017 Multi-University Training Contest - Team 10
题目大意:求
1
到
解题思路:
A∗
算法可以用来求第
k
短路,当然也可以用来求次短路。
第
注:
另解:此题也可以直接用求次短路的方法(在
Dijkstra
上进行少许修改)解决。到某个顶点
v
的次短路要么是到其他某个顶点
注:次短路算法的题目可以看POJ3255
A∗ 解法:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;
const LL INF=1e18;
const int MAXN=1e5+5;
int head[MAXN],head1[MAXN];
LL dis[MAXN];
bool vis[MAXN];
int n,m,tot,st,en,k;
struct Edge
{
int u,v,nxt,nxt1;
LL c;
Edge(){}
Edge(int _u,int _v,LL _c):u(_u),v(_v),c(_c){}
}e[MAXN*2];
struct qnode
{
int v;
LL c;
qnode(){}
qnode(int _v,LL _c):v(_v),c(_c){}
bool operator < (const qnode& rhs) const
{
return c+dis[v]>rhs.c+dis[rhs.v];
}
};
void addedge(int u,int v,LL c)
{
e[tot]=Edge(u,v,c);
e[tot].nxt=head[u];head[u]=tot;
e[tot].nxt1=head1[v];head1[v]=tot++;
}
void dij(int src)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++) dis[i]=INF;
dis[src]=0;
priority_queue<qnode> que;
que.push(qnode(src,0));
while(!que.empty())
{
qnode pre=que.top(); que.pop();
if(vis[pre.v]) continue;
vis[pre.v]=true;
for(int i=head1[pre.v];i!=-1;i=e[i].nxt1)
{
if(dis[e[i].u]>dis[pre.v]+e[i].c)
{
dis[e[i].u]=dis[pre.v]+e[i].c;
que.push(qnode(e[i].u,0));
}
}
}
}
LL a_star(int src)
{
priority_queue<qnode> que;
que.push(qnode(src,0));
k--;
while(!que.empty())
{
qnode pre=que.top();que.pop();
if(pre.v==en)
{
if(k) k--;
else return pre.c;
}
for(int i=head[pre.v];i!=-1;i=e[i].nxt)
que.push(qnode(e[i].v,pre.c+e[i].c));
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
tot=0;
for(int i=0;i<m;i++)
{
int u,v;LL c;
scanf("%d%d%lld",&u,&v,&c);
addedge(u,v,c);
addedge(v,u,c);
}
st=1,en=n;k=2;
dij(en);
if(st==en) k++;
printf("%lld\n",a_star(st));
}
return 0;
}
次短路解法:
///求次短路
///使用优先队列Dijkstra算法
///复杂度O(ElogV)
///注意初始化
///dist2[v]=min(dist[u]+e(u,v),dist2[u]+e(u,v))
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<fstream>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int MAXN=1e5+5;
const int MAXM=2e5+5;
const LL INF=1e18;
LL dist[MAXN];
int head[MAXN],tot;
LL dist2[MAXN];//次短距离
int pre[MAXN];
struct Edge
{
int from,to,nxt;
LL cost;
Edge(){}
Edge(int _from,int _to,LL _cost):from(_from),to(_to),cost(_cost){}
}e[MAXM];
void addedge(int u,int v,int w)
{
e[tot].from=u;e[tot].to=v;e[tot].cost=w;
e[tot].nxt=head[u];head[u]=tot++;
}
struct qnode
{
int v;
LL c;
qnode(LL _c=0,int _v=0):c(_c),v(_v){}
bool operator < (const qnode &rhs) const {return c>rhs.c;}
};
void Dijkstra(int n,int st)//点的编号从1开始
{
for(int i=0;i<=n;i++) dist[i]=INF,dist2[i]=INF;
priority_queue<qnode> pq;
while(!pq.empty()) pq.pop();
dist[st]=0;
pq.push(qnode(0,st));
qnode frt;
while(!pq.empty())
{
frt=pq.top(); pq.pop();
int u=frt.v;
LL d=frt.c;
if(dist2[u]<d) continue;
for(int i=head[u];i!=-1;i=e[i].nxt)
{
int to=e[i].to;
LL cost=e[i].cost;
LL d2=d+cost;
if(dist[to]>d2)
{
swap(dist[to],d2);
pre[to]=u;
pq.push(qnode(dist[to],to));
}
if(dist2[to]>d2&&dist[to]<d2)
{
dist2[to]=d2;
pq.push(qnode(dist2[to],to));
}
}
}
}
int main()
{
int T;
int vN,eN;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&vN,&eN);
tot=0;memset(head,-1,sizeof(head));
int u,v,w;
for(int i=1;i<=eN;i++)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);addedge(v,u,w);
}
int st,ed;
st=1,ed=vN;
//scanf("%d%d",&st,&ed);
//if(st==ed) {printf("0\n");continue;}
Dijkstra(vN,st);
// for(int i=0;i<=vN-1;i++)
// printf("%d ",dist[i]);
// printf("\n");
// for(int i=0;i<=vN-1;i++)
// printf("%d ",pre[i]);
// printf("\n");
printf("%lld\n",dist2[ed]);
}
return 0;
}
/*
1
4 6
1 2 1
1 2 5
1 3 2
2 3 2
2 4 1
2 4 6
ans:4
*/