您的位置:首页 > 其它

hdu 6181 Two Paths(最短路,spfa)

2017-08-28 20:10 393 查看

题目链接:传送门

Two Paths

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 153428/153428 K (Java/Others)

Total Submission(s): 971 Accepted Submission(s): 450

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

题目大意:n个点,m条边,每条边有一个权值,除最短路外,再找一条最短路。

要求:只要两个最短路中有一步不同,那么这两个最短路就不同。

如第二个样例:1——2为最短路,那么第二个最短路就是1——2——1——2,因为第二步和第四步不同(即使第一个最短路没有,第二步和第四步)。

还有最坑的样例:3个点,3条边,1-3 3 1-2 1 2-3 100

最短路为1-3,第二条最短路为1-2-1-3;

思路:找出最短路径,并记录,依次去掉最短路中的一步,并记录他们的最短路(这是不依靠原先的最短路),然后再寻找链接着最短路点的最短的那一条边,最短路加2*最短的边长(这是依靠原先的最短路,如上述讲的例子)。

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;

#define LL long long
const LL inf=1e18+9;
const int N=350015;
struct node
{
LL w;
int v;
int nex;
} e[N*4];
int firs[N*4],tot;
void edge(int u,int v,LL w)//建立邻接表
{
e[tot].w=w;
e[tot]
c724
.v=v;
e[tot].nex=firs[u];
firs[u]=tot++;
}
LL dis
;//记录最短路
int vis
;
struct nodee
{
int xia;//最短路的点
int lon;//到该点的路径的编号
} lu
;//记录最短路的路径
int n,m;
void spfa(int u,int flag)//求最短路
{
for(int i=1; i<=n; i++)
{
dis[i]=inf;
vis[i]=0;
}
dis[u]=0;
vis[u]=1;
queue<int>q;
q.push(u);
while(!q.empty())
{
int p=q.front();
q.pop();
vis[p]=0;
for(int i=firs[p]; i!=-1; i=e[i].nex)
{
if(dis[p]+e[i].w<dis[e[i].v])
{
if(flag)//记录路径
{
lu[e[i].v].xia=p;
lu[e[i].v].lon=i;
}
dis[e[i].v]=dis[p]+e[i].w;
if(!vis[e[i].v])
{
vis[e[i].v]=1;
q.push(e[i].v);
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(firs,-1,sizeof(firs));
scanf("%d%d",&n,&m);
tot=0;
for(int i=0; i<m; i++)
{
int a,b;
LL c;
scanf("%d%d%lld",&a,&b,&c);
edge(a,b,c);//无向边,建立邻接表
edge(b,a,c);
}
for(int i=0; i<=n; i++)//用邻接表记录路径
lu[i].xia=i;
spfa(1,1);
LL dd=dis
;
LL maxx=inf;//与最短路上的点有关的最短的路
int f=n;
LL maxxx=inf;//记录第二条最短路
while(f!=lu[f].xia)//遍历最短路
{
int ff=lu[f].lon;
maxx=min(maxx,e[ff].w);
for(int i=firs[f]; i!=-1; i=e[i].nex)//寻找与最短路上点有关的最短的边长
{
maxx=min(maxx,e[i].w);
}
LL p=e[ff].w;
e[ff].w=inf;//先删去该路径
spfa(1,0);
e[ff].w=p;//恢复该路径
f=lu[f].xia;
maxxx=min(maxxx,dis
);
}
for(int i=firs[1]; i!=-1; i=e[i].nex)//寻找与起点1有关的最短的边长
{
maxx=min(maxx,e[i].w);
}
maxxx=min(maxxx,dd+maxx+maxx);
printf("%lld\n",maxxx);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: