天天写算法之(最短路)Cycling

地址: 点击打开链接
这个题目,怎么说呢,一开始我看到这个题目,想到的时,把高度替换一下,然后找最短路,记录下路径,随后再去找真的最短路。后来发现不太可行,因为可能不止一个。而且也不太好判断。于是网上找了一波,不太习惯spfa算法,还是习惯dj。所以找到了一个,还没有来得及敲代码。整体思路,就是把所有的高度差都列一遍,然后dj看能不能到,能到就更新,不能到接着算。

代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 0x3f3f3f3f ;
struct Node{
    int h ;
    int num ;
}node[110] ;
int T ,N,M;
int map[110][110] ;
bool with[110];

bool comp(Node n1, Node n2){
    return n1.h < n2.h ;
}
bool vis[110] ;
int dis[110] ;
int min_h , min_d ;
struct Node1{
    Node1(int a, int b)
    :d(a) , num(b) {}
    int d ,num ;
    friend bool operator <(const Node1& n1 , const Node1 &n2){
        if(n1.d == n2.d)    return n1.num < n2.num ;
        return n1.d > n2.d ;
    }
};
priority_queue<Node1> que ;
int Dij(){
    while(!que.empty())     que.pop() ;
    for(int i=2;i<=N;i++){
        vis[i] = 0 ;
        if(with[i] == 0)    continue ;
        que.push( Node1( map[1][i] , i)) ;
        dis[i] = map[1][i] ;
    }
    que.push( Node1(0,1) ) ;
    dis[1] = 0 ;
    for(int i=1;i<=N;i++){
        while(vis[que.top().num]==1)    que.pop() ;
        int min_n = que.top().num ;
        int _min = que.top().d ;
        que.pop() ;
        vis[min_n] = 1 ;
        if(min_n == N)  return _min ;
        for(int j=1;j<=N;j++){
            if(vis[j]==1 || with[j]==0) continue ;
            if(dis[j] > dis[min_n] + map[min_n][j] ){
                dis[j] = dis[min_n] + map[min_n][j] ;
                que.push( Node1(dis[j] , j) ) ;
            }
        }
    }
}
void solve(){
    for(int i=1;i<=N;i++){
        for(int j=i;j<=N;j++){
            memset(with ,0 ,sizeof(with) );
            int min_len = node[i].h ;
            int max_len = node[j].h ;
            for(int k=1;k<=N;k++){
                if(node[k].h >= min_len && node[k].h<=max_len){
                    with[ node[k].num ] = 1;
                }
            }
            if(with[1]==0 || with[N]==0)    continue ;
            Dij() ;
            if(dis[N] != INF){
                if(max_len - min_len < min_h){
                    min_h = max_len  - min_len ;
                    min_d = dis[N] ;
                }
                else if(max_len - min_len == min_h){
                    if(min_d > dis[N])
                        min_d = dis[N] ;
                }
            }
        }
    }
    printf("%d %d\n",min_h,min_d);
}
int main(){
    int a ,b, c;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&N,&M);
        for(int i=1;i<=N;i++){
            scanf("%d",&node[i].h);
            node[i].num = i ;
        }
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                if(i == j)  map[i][j] = 0 ;
                else        map[i][j] = INF ;
            }
        }
        for(int i=1;i<=M;i++){
            scanf("%d %d %d",&a,&b,&c);
            if(map[a][b] > c){
                map[a][b] = map[b][a] = c ;
            }
        }
        sort(node+1, node+1+N , comp);
        min_h = INF ; min_d = INF ;
        solve();
    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/qq_36616268/article/details/80556112