POJ-3255-次短路问题

Roadblocks

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7149   Accepted: 2663

Description

Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too quickly, because she likes the scenery along the way. She has decided to take the second-shortest rather than the
shortest path. She knows there must be some second-shortest path.

The countryside consists of R (1 ≤ R ≤ 100,000) bidirectional roads, each linking two of the N (1 ≤
N ≤ 5000) intersections, conveniently numbered 1..N. Bessie starts at intersection 1, and her friend (the destination) is at intersection
N.

The second-shortest path may share roads with any of the shortest paths, and it may backtrack i.e., use the same road or intersection more than once. The second-shortest path is the shortest path whose length is longer than the shortest path(s) (i.e., if
two or more shortest paths exist, the second-shortest path is the one whose length is longer than those but no longer than any other path).

Input

Line 1: Two space-separated integers: N and
R

Lines 2..R+1: Each line contains three space-separated integers: A,
B, and D that describe a road that connects intersections A and
B and has length D (1 ≤ D ≤ 5000)

Output

Line 1: The length of the second shortest path between node 1 and node
N

Sample Input

4 4
1 2 100
2 4 200
2 3 250
3 4 100

Sample Output

450

Hint

Two routes: 1 -> 2 -> 4 (length 100+200=300) and 1 -> 2 -> 3 -> 4 (length 100+250+100=450)

Source

USACO 2006 November Gold

本题目的意思就是要求次短路。我用两种方法求解:

(一)利用dijkstra算法进行适当修改,到某个顶点v的次短路:(1)其他某个顶点u的最短路加上u->v的边长;(2)其他某个顶点u的次短路加上u->v的边长。所以我们要求出到所有

顶点的最短路和次短路。因此对每个顶点,同时记录最短距离和次短距离(开两个数组记录,用dijkstra算法不断更新)。

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

const int INF=1000000000;
const int max_e=200000+5;
typedef pair<int,int>P;
struct edge{
    int to,dis;
    edge(int to,int dis){
        this -> to = to;
        this -> dis = dis;
    }
};
int N,R;
int a,b,c;
int dis[5005];         //记录最短路径
int disc[5005];       //记录次短路径
vector<edge>G[max_e];

void dijkstra(){
    fill(dis+1,dis+N+1,INF);
    fill(disc+1,disc+N+1,INF);
    priority_queue<P,vector<P>,greater<P> >q;
    dis[1]=0;
    q.push(P(0,1));
    while(q.size()){
        P p=q.top();
        q.pop();
        int dd=p.first;
        int v=p.second;
        if(disc[v]<dd) continue;
        for(int i=0;i<G[v].size();i++){
            edge& e=G[v][i];
            int d=dd+e.dis;
            if(dis[e.to]>d){
                swap(dis[e.to],d);
                q.push(P(dis[e.to],e.to));
            }
            if(disc[e.to]>d&&dis[e.to]<d){
                disc[e.to]=d;
                q.push(P(disc[e.to],e.to));
            }
        }
    }
    cout<<disc[N]<<endl;
}

int main()
{
    scanf("%d%d",&N,&R);
    for(int i=1;i<=R;i++){
        scanf("%d%d%d",&a,&b,&c);
        G[a].push_back(edge(b,c));
        G[b].push_back(edge(a,c));
    }
    dijkstra();
    return 0;
}

(二)一个巧妙的方法,利用dijkstra双向求出起点到每一点的最短路,以及每一点到终点的最短路径,然后枚举每一条边,就可以得到次短路了。此方法也可以拓展成求第K短

路问题,不过要注意时间复杂度。

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

const int INF=1000000000;
const int max_e=200000+5;
typedef pair<int,int>P;
struct edge{
    int to,dis;
    edge(int to,int dis){
        this -> to = to;
        this -> dis = dis;
    }
};
struct dd{
    int x,y;
    int sum;
}an[200005];

int N,R;
int a,b,c;
int d1[5005];
int d2[5005];
vector<edge>G[max_e];

void dijkstra(int dis[],int s){
    fill(dis+1,dis+N+1,INF);
    priority_queue<P,vector<P>,greater<P> >q;
    dis[s]=0;
    q.push(P(0,s));
    while(q.size()){
        P p=q.top();
        q.pop();
        int v=p.second;
        if(dis[v]<p.first) continue;
        for(int i=0;i<G[v].size();i++){
            edge& e=G[v][i];
            if(dis[e.to]>dis[v]+e.dis){
                dis[e.to]=dis[v]+e.dis;
                q.push(P(dis[e.to],e.to));
            }
        }
    }
}

int main()
{
    int K=0;
    scanf("%d%d",&N,&R);
    for(int i=1;i<=R;i++){
        scanf("%d%d%d",&a,&b,&c);
        G[a].push_back(edge(b,c));
        G[b].push_back(edge(a,c));
        an[K].x=a; an[K].y=b; an[K].sum=c; K++;
        an[K].x=b; an[K].y=a; an[K].sum=c; K++;
    }
    dijkstra(d1,1);
    dijkstra(d2,N);
    int ans=INF;    //cout<<ans<<" "<<d1[N]<<endl;
    for(int i=1;i<=K;i++){
        int aa=d1[an[i].x]+d2[an[i].y]+an[i].sum;
        if(aa>d1[N]){
            ans=min(ans,aa);
        }
    }cout<<ans<<endl;
    return 0;
}

POJ-3255-次短路问题

时间: 2024-08-10 22:37:43

POJ-3255-次短路问题的相关文章

Roadblocks POJ 3255(次短路)

原题 题目链接 题目分析 给无向图,求次短路.相对于第k短路而言次短路还是好求的,只需要在跑dijkstra的过程中顺便记录次短路就行了. 代码 1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <algorithm> 5 #include <utility> 6 #include <ctime> 7 #include <cmath

POJ 3255 &amp;&amp; HDU 1688 &amp;&amp; HDU 3191 次短路问题

POJ 3255 Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7627   Accepted: 2798 Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old h

POJ 3255 Roadblocks (次短路问题)

解法有很多奇葩的地方,比如可以到达终点再跳回去再跳回来(比如有两个点)....反正就是不能有最短路,不过没关系,算法都能给出正确结果 思想:和求最短路上的点套路一样,spfa先正着求一次,再反着求一次最短路,然后枚举每条边<i,j>找dist_zheng[i] + len<i,j> + dist_fan[j]的第二小值即可!注意不能用邻接矩阵,那样会MLE,应该用邻接表 /* poj 3255 3808K 266MS */ #include<cstdio> #inclu

poj 3255 Roadblocks【次短路】

题目:poj 3255 Roadblocks 题意:给出一个无向图,然后求1到n点的次短路 分析:两种做法,第一种,Astat+最短路求k短路的方法. 第二种是比较暴力的方法. 先求1点到所有点的最短路dis1 然后求n点到所有点的最短路dis2 然后枚举所有边,则次短路为dis1[from] + dis2[to] + w[i]中大于最短路的最短的. AC代码: #include <cstdio> #include <string> #include <cstring>

POJ - 3255 Roadblocks (次短路)

POJ - 3255 Roadblocks Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Submit Status Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her

如何用求次长边——POJ 3255 题解

题目大意 给你一个 \(n\) 个点,\(m\) 条边的无向图,求出这个无向图中从1到n的次短路.其中\(n \le 5000\),\(m \le 100000\). 题目传送门 POJ 3255 思路 其实求次长路是很简单的一个问题,但是网上却有很多算法都过于复杂了.首先我们先求出从1到每个结点的最短路长度(用Dijkstra或者是SPFA都可以),存入数组 \(dis1\) 中,然后再求出从结点 \(n\) 到任意结点的最短路的长度,存入数组 \(dis2\) 中. 然后我们枚举这个图中的所

poj 1502 最短路+坑爹题意

链接:http://poj.org/problem?id=1502 MPI Maelstrom Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5249   Accepted: 3237 Description BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed share

POJ 2448(K短路,A*+SPFA) Remmarguts&#39; Date

题意 给一个n个点m条边的图,然后给一个起点和一个终点,求起点到终点的第K短路. 思路 求第K短路.一个经典的问题. SPFA+A* 核心思想在A*搜索的估计函数的建立上. F(x) = g(x) + h(x) 估价函数 = s到x的距离 + x到t的距离 估价函数的含义就是经过x这个点的路径的距离. 我们在搜索的时候每次选择估价函数较小的值,进行拓展.这样我们搜索到t点的状态出来顺序就是,最短路-次短路-.第三短路- 就减少了我们搜索的状态数. 代码实现上,实现一个估价函数的结构体,然后是实现

poj 1135 最短路 dijkstra

传送门 http://poj.org/problem?id=1135 建模分两部分:1.如果最后是关键牌倒下,那么找最短路中最长的就行--最远的倒下,其他的牌一定倒下,所以找最远的最短路 2.如果最后是普通牌倒下,那么找三角形,三角形周长的一半就是倒下的位置 到底是情况1还是情况2,自己在脑子模拟一下就能想到,还是那句话,最难倒下的倒下了,其他的一定都倒下了,若第二种情况的时间比第一种长,那么就是第二种,反之,第一种 上代码 /**********************************

It&amp;#39;s not a Bug, It&amp;#39;s a Feature! (poj 1482 最短路SPFA+隐式图+位运算)

Language: Default It's not a Bug, It's a Feature! Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 1353   Accepted: 516 Description It is a curious fact that consumers buying a new software product generally do not expect the software to