您的位置:首页 > 大数据 > 人工智能

2017 Multi-University Training Contest 10 1011 Two Paths HDU 6181 (次短路+最短路数量)

2017-08-24 22:10 507 查看


Two Paths

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

Total Submission(s): 0    Accepted Submission(s): 0


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

 

Statistic | Submit | Clarifications | Back

题意:给你一个有向图,问你他的次短路长度(与最短路至少有一条边不同即可)

思路:如果最短路有多条,那答案就是最短路,否则就是次短路,维护一个最短路数量,然后就是求次短路了(细节详见注释)

求次短路(见点击打开链接):

    思路: 

        把求最短路时更新最短路的那部分改一下。 

        dis1,dis2数组分别记录到该点的最短路和次短路 

        分三种情况: 

            1.若该点最短路+下一条边比到下个点的最短路短,则更新下个点的最短路,同时更新次短路为原最短路 

            2.若该点次短路+下一条边比到下个点的次短路短,则更新下个点的次短路 

            3.若该点最短路+下一条边比到下个点的最短路长同时比下个点的次短路短,则更新下个点的次短路 

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, head[maxn];
ll cnt[maxn];
ll dis1[maxn], dis2[maxn], dis[maxn];
bool book[maxn];

struct node
{
int v, w, next;
}edge[maxn];

void addEdge(int u, int v, int w)
{
edge[k].v = v;
edge[k].w = w;
edge[k].next = head[u];
head[u] = k++;
}

void spfa(int u)
{
for(int i = 1; i <= n; i++) dis1[i] = INF;
for(int i = 1; i <= n; i++) dis2[i] = INF;
memset(book, 0, sizeof(book));
queue<int> q;
q.push(u);
dis1[u] = 0;
book[u] = 1;
while(!q.empty())
{
u = q.front(); q.pop();
book[u] = 0;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if(dis1[v] > dis1[u]+w)
{
dis2[v] = dis1[v];
dis1[v] = dis1[u]+w;
if(!book[v]) book[v] = 1, q.push(v);
}
if(dis2[v] > dis2[u]+w)
{
dis2[v] = dis2[u]+w;
if(!book[v]) book[v] = 1, q.push(v);
}
if(dis1[v] < dis1[u]+w && dis2[v] > dis1[u]+w)
{
dis2[v] = dis1[u]+w;
if(!book[v]) book[v] = 1, q.push(v);
}
}
}
}

void spfa2(int u)  //求有几个最短路
{
for(int i = 1; i <= n; i++) dis[i] = INF;
memset(book, 0, sizeof(book));
queue<int> q;
q.push(u);
book[u] = cnt[u] = 1;
dis[u] = 0;
while(!q.empty())
{
u = q.front(); q.pop();
book[u] = 0;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
int w = edge[i].w;
if(dis[u]+w < dis[v])
{
dis[v] = dis[u]+w;
if(!book[v]) book[v] = 1, q.push(v);
cnt[v] = cnt[u];    //如果更新最短路,数组更新
}
else if(dis[u]+w == dis[v])
{
cnt[v] += cnt[u];  //如果相同说明都可以作为一个最短路的边,v+上u的种类
}
}
}
}

int main(void)
{
int t;
cin >> t;
while(t--)
{
k = 0;
memset(cnt, 0, sizeof(cnt));
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
}
spfa(1);
spfa2(1);
if(cnt
> 1) printf("%lld\n", dis1
);
else printf("%lld\n", dis2
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐