HDU Shortest path

本文介绍了一种使用三分法解决特定最短路径问题的方法。该问题要求从城市1到城市N找到一条路径,使得经过边的长度严格递增。通过排序边并应用三分法,实现了高效求解。

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

原文链接 http://acm.hdu.edu.cn/showproblem.php?pid=4479

Shortest path

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 203    Accepted Submission(s): 67


Problem Description
  There are N cities (marked by 1, 2, …, N) and M bidirectional roads in the kingdom. There may be several roads between any two cities, but there is not any road connects the same city.
Your task is to find a shortest path from city 1 to city N, and the lengths of the edges you passed by must be strictly in increasing order.
 


Input
  There is an integer T (1 <= T <= 500) in the first line, indicates that there are T test cases in total.
  For each test case, there are two integers N (2 <= N <= 10000) and M (1 <= M <= 50000), which have the same meaning as above. Then there are M lines, and there are three integers x (1 <= x <= N), y (1 <= y <= N), and z (1 <= z <= 10000000) in each line, indicate there is a bidirectional road between city x and city y.
    There are at most ten test cases that satisfy that N > 200 or M > 1000.
 


Output
  For each test case, you should output the length of the shortest path you find in the above task.
  If such path does not exist, you should just output “No answer” (without quotation mark) instead.
 


Sample Input
  
4 4 6 1 2 1 1 2 2 2 3 3 2 3 1 3 4 2 4 3 6 3 2 1 2 1 2 3 1 3 1 1 2 1 2 2 2 1 1 1 2 2
 


Sample Output
  
10 No answer No answer 1
 做这道提目是队长拉的一次比赛,读懂了题目,真心不知道用什么方法,后来看了题解知道用了三分,汗颜啊,三分要好好学习了,附上大神的代码。
因为满足函数凸(凹)性,所以直接用三分。
#include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef __int64 LL;
const LL maxn = 10005;
const LL maxm = 50005;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
struct node{
    int u,v,len;
    bool operator < (node a)const{
        return len < a.len;
    }

}edge[maxm];

LL dis[maxn];
int id,n,m;

struct Rec{
    int v;
    LL d;
}rec[maxn];

void update(int l,int r){
    int index = 0;
    for(int i = l; i <= r; i++){
        int u = edge[i].u,v = edge[i].v,len = edge[i].len;
        if( dis[u] != INF && dis[v] > dis[u] + len )
        rec[index].v  = v,rec[index++].d = dis[u] + len;
        if( dis[v] != INF && dis[u] > dis[v] + len)
        rec[index].v = u,rec[index++].d = dis[v] + len;
    }
    for(int i = 0; i < index; i++)
    dis[rec[i].v] = min(dis[rec[i].v],rec[i].d);

}

void slove(){
    memset(dis,0x3f,sizeof(dis));
    //cout << dis[0] << endl;
    dis[1] = 0;
    for(int i = 0,j; i < m; i = j){
        for( j = i+1; j < m ;j ++)
        if( edge[i].len != edge[j].len)
        break;
        update(i,j-1);
    }
}

int main(){
    int t;
    scanf("%d",&t);
    while( t-- ){
        scanf("%d%d",&n,&m);
        for(int i = 0; i < m; i++)
        scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].len);
        sort(edge,edge+m);
        slove();
        if( dis[n] == INF)puts("No answer");
        else printf("%I64d\n",dis[n]);
    }
    return 0;

}

 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值