您的位置:首页 > 其它

hdu 6181 Two Paths -最短路条数+次短路 - 多校联盟10

2017-08-24 17:48 417 查看

Two Paths

[b]Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 37    Accepted Submission(s): 24
[/b]

[align=left]Problem Description[/align]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.
 
[align=left]Input[/align]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.
 
[align=left]Output[/align]For each test case print length of valid shortest path in one line. 
[align=left]Sample Input[/align]
2
3 3
1 2 1
2 3 4
1 3 3
2 1
1 2 1 
[align=left]Sample Output[/align]
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
 
[align=left]Source[/align]2017 Multi-University Training Contest - Team 10

代码:整合版
/*
题意:
n点m条边的无向图,第一个人走最短路,
第二个人在满足走和第一个人不同的路(只要其中一个边不同就行)的条件下
路径最短是多少
解题思路:
如果图中存在多条最短路,那么输出最短路用的时间否则输出次短路用的时间

最短路条数:
当dist[v]+e.cost < dist[e.to]时,最短路只能从v走到e.to,所以cnt[e.to] = cnt[v];
当dist[v]+e.cost = dist[e.to]时,最短路可以从v走到e.to,所以cnt[e.to] += cnt[v];

次短路:
到顶点v的次短路要么是最短路dist[u]+G[u][v],要么是次短路dist2[u]+G[u][v],
所以求出每个点的最短路和次短路,最后与dijkstra做法相同不断更新这两个距离
*/

#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <utility>
#define INF 0x3f3f3f3f
using namespace std;

typedef unsigned long long ll;
typedef pair<ll,ll> P;

const int maxn=100000+10;

ll n,r;//n个点,r条边
ll dist[maxn];
ll dist2[maxn];

struct edge
{
ll to;
ll cost;
};
vector<edge> G[maxn];
ll cnt[maxn];

void solve(){

///次短路和最短路整合
priority_queue<P,vector<P>,greater<P> > que;
memset(dist,INF,sizeof(dist));
memset(dist2,INF,sizeof(dist2));
memset(cnt, 0, sizeof(cnt));
cnt[0] = 1;
dist[0] = 0;
que.push(P(0,0) );
while(!que.empty()){
P p = que.top();
que.pop();
ll v = p.second;
ll d = p.first;
if(dist2[v] < d) continue;

for(ll i = 0;i<G[v].size();++i){
edge &e = G[v][i];
ll d2 = d+e.cost;
if(dist[e.to] > d2){
swap(dist[e.to],d2);
cnt[e.to] = cnt[v];
que.push(P(dist[e.to],e.to));
}else if (d2 == dist[e.to]){///d2等价于dist[v]+ e.cost
if(!(dist[v] < d)) ///避免使用未更新过的值重复加,并且if(dist[v] < d) continue;不可放到61行会影响dist2取值
cnt[e.to] += cnt[v];
}
if(dist2[e.to] > d2 && dist[e.to] < d2){///保证将更新的次短路的值是大于最短路的
dist2[e.to] = d2;
que.push(P(dist2[e.to],e.to));
}
}
}
if (cnt[n-1] > 1){
cout << dist[n-1] << endl;
return;
}
printf("%lld\n",dist2[n-1]);
}

int main()
{
int t;
scanf("%d",&t);
while(t--){
//初始化map
for(ll i = 0;i<maxn;++i) G[i].clear();
scanf("%d%d",&n,&r);
for(ll i=0;i<r;++i)
{
edge temp,temp1;
ll u,v;
ll w;
scanf("%lld%lld%lld",&u,&v,&w);
temp.to = v-1;
temp.cost = w;
temp1.to =u-1;
temp1.cost=w;
G[u-1].push_back(temp);
G[v-1].push_back(temp1);
}
solve();

}

return 0;
}
代码:分开版

/*
题意:
n点m条边的无向图,第一个人走最短路,
第二个人在满足走和第一个人不同的路(只要其中一个边不同就行)的条件下
路径最短是多少
解题思路:
如果图中存在多条最短路,那么输出最短路用的时间否则输出次短路用的时间

最短路条数:
当dist[v]+e.cost < dist[e.to]时,最短路只能从v走到e.to,所以cnt[e.to] = cnt[v];
当dist[v]+e.cost = dist[e.to]时,最短路可以从v走到e.to,所以cnt[e.to] += cnt[v];

次短路:
到顶点v的次短路要么是最短路dist[u]+G[u][v],要么是次短路dist2[u]+G[u][v],
所以求出每个点的最短路和次短路,最后与dijkstra做法相同不断更新这两个距离
*/

#include <cstring>
#include <cstdio>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <utility>
#define INF 0x3f3f3f3f
using namespace std;

typedef unsigned long long ll;
typedef pair<ll,ll> P;

const int maxn=100000+10;

ll n,r;//n个点,r条边
ll dist[maxn];
ll dist2[maxn];

struct edge
{
ll to;
ll cost;
};
vector<edge> G[maxn];
ll cnt[maxn];

///最短路条数
void dij_cnt(){
priority_queue<P,vector<P>,greater<P> > que;
memset(dist,INF,sizeof(dist));
memset(cnt, 0, sizeof(cnt));
dist[0] = 0;
que.push(P(0,0));
cnt[0] = 1;
while(!que.empty()){
P p = que.top();que.pop();
ll v = p.second;
if(dist[v]<p.first) continue;
for(ll i = 0;i<G[v].size();++i){
edge &e = G[v][i];
if (dist[v]+e.cost < dist[e.to]){
dist[e.to] = dist[v]+e.cost;
cnt[e.to] = cnt[v];
que.push(P(dist[e.to],e.to));
}else if (dist[v]+e.cost == dist[e.to]){
cnt[e.to] += cnt[v];
}
}
}
}

void solve(){

dij_cnt();
if (cnt[n-1] > 1){
cout << dist[n-1] << endl;
return;
}
///次短路模板
priority_queue<P,vector<P>,greater<P> > que;
memset(dist,INF,sizeof(dist));
memset(dist2,INF,sizeof(dist2));
dist[0] = 0;
que.push(P(0,0) );
while(!que.empty()){
P p = que.top();
que.pop();
ll v = p.second;
ll d = p.first;
if(dist2[v] < d) continue;
for(ll i = 0;i<G[v].size();++i){
edge &e = G[v][i];
ll d2 = d+e.cost;
if(dist[e.to] > d2){
swap(dist[e.to],d2);
que.push(P(dist[e.to],e.to));
}
if(dist2[e.to]>d2 && dist[e.to]<d2){
dist2[e.to] = d2;
que.push(P(dist2[e.to],e.to));
}
}
}
printf("%lld\n",dist2[n-1]);
}

int main()
{
int t;
scanf("%d",&t);
while(t--){
//初始化map
for(ll i = 0;i<maxn;++i) G[i].clear();
scanf("%d%d",&n,&r);
for(ll i=0;i<r;++i)
{
edge temp,temp1;
ll u,v;
ll w;
scanf("%lld%lld%lld",&u,&v,&w);
temp.to = v-1;
temp.cost = w;
temp1.to =u-1;
temp1.cost=w;
G[u-1].push_back(temp);
G[v-1].push_back(temp1);
}
solve();

}

return 0;
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息