HDU 6181 Two Paths

本文介绍了一种求解次短路径的算法实现,通过SPFA预处理最短路径,并结合A*搜索策略找到与最短路径不同的另一条有效路径。适用于解决特定类型的图论问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Two Paths

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 153428/153428 K (Java/Others)
Total Submission(s): 110    Accepted Submission(s): 70


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
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6181  6180  6179  6178  6177 

题意:
求出与最短路不相同的一条次短路(似乎并不是严格的次短路,只需稍微与最短路有点不同即可)
思路:
我直接套上第k短路板子过了,因为是无向图,所以不用再建新图。

示例程序:

#include <bits/stdc++.h>
#define MAX 100000000000000
using namespace std;
struct jj
{
    int v,next;
    long long c;
}w[200000];
struct kk
{
    int v;
    long long g,f;
    bool operator<(const struct kk &a) const
    {
        if(a.f<f)
        {
            return 1;
        }
        else if(a.f==f&&a.g<g)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
};
int h[100001],numw;
long long dis[100001];
void insert(int u,int v,long long c)
{
    w[numw].v=v;
    w[numw].c=c;
    w[numw].next=h[u];
    h[u]=numw++;
}
void spfa(int s)
{
    int i,v[100001];
    queue<int>q;
    for(i=1;s>=i;i++)
    {
        dis[i]=MAX;
        v[i]=0;
    }
    dis[s]=0;
    q.push(s);
    while(q.empty()==0)
    {
        s=q.front();
        q.pop();
        v[s]=0;
        for(i=h[s];i!=-1;i=w[i].next)
        {
            if(dis[w[i].v]>dis[s]+w[i].c)
            {
                dis[w[i].v]=dis[s]+w[i].c;
                if(v[w[i].v]==0)
                {
                    v[w[i].v]=1;
                    q.push(w[i].v);
                }
            }
        }
    }
}
long long A_star(int s,int t)
{
    int i,v[100001],num=0;
    struct kk pre,pos;
    priority_queue<struct kk>q;
    memset(v,0,sizeof(v));
    pos.v=s;
    pos.g=0;
    pos.f=pos.g+dis[s];
    q.push(pos);
    while(q.empty()==0)
    {
        pre=q.top();
        q.pop();
        for(i=h[pre.v];i!=-1;i=w[i].next)
        {
            if(v[w[i].v]==3)           //剪枝,一个点最多访问三次
            {
                continue;
            }
            pos.v=w[i].v;
            pos.g=pre.g+w[i].c;
            pos.f=pos.g+dis[w[i].v];
            if(pos.v==t)            //找到一条最短路径
            {
                num++;
            }
            if(num==2)              //找到k(次)短路
            {
                return pos.g;
            }
            v[w[i].v]++;
            q.push(pos);
        }
    }
}
int main()
{
    int t,n,m,i,u,v;
    long long c;
    scanf("%d",&t);
    while(t--)
    {
        memset(h,-1,sizeof(h));
        numw=0;
        scanf("%d %d",&n,&m);
        for(i=1;m>=i;i++)
        {
            scanf("%d %d %lld",&u,&v,&c);
            insert(u,v,c);
            insert(v,u,c);
        }
        spfa(n);
        printf("%lld\n",A_star(1,n));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值