1. 程式人生 > 實用技巧 >鏈式前向星&&dij堆優化

鏈式前向星&&dij堆優化

鏈式前向星

\(next\)指的是上一條同起點邊的位置,\(to\)表示這條邊的終點,\(val\)表示邊權。

\(u、v、val\)分別表示起點,終點,邊權。

\(head[x]\)存以\(x\)為起點的,最後加入的邊的位置\(edge[edge[u]]\)

struct node{
    int next,to,val;
}edge[maxn];
int head[maxn];
int tot=0;
head[x]=-1;
void add(int u,int v,int val){
    edge[++tot].to=v;
    edge[tot].val=val;
    edge[tot].next=head[u];
    head[u]=tot;
}

dij堆優化

priority_queue<pii,vector<pii >,greater<pii > >qp;
int dis[maxn],vis[maxn];
void dijkstra(int src){
    for(int i=1;i<=n;++i){
        dis[i]=INF;
    }
    dis[src]=0;
   qp.push({0,src});
    while(!qp.empty()){
        pii t=qp.top;qp.pop();
        int u=t.second;
        if(vis[u])continue;
        vis[u]=1;
        for(int i=head[u];i;i=edge[i].next){
            if(dis[edge[i].to]>dis[u]+edge[i].val){
                dis[edge[i].to]=dis[u]+edge[i].val;
                qp.push({dis[edge[i].to],edge[i].to});
            }
        }
    }
}

連結:https://ac.nowcoder.com/acm/problem/14550
來源:牛客網

題目描述

小z放假了,準備到RRR城市旅行,其中這個城市有N個旅遊景點。小z時間有限,只能在三個旅行景點進行遊玩。小明租了輛車,司機很善良,說咱不計路程,只要你一次性繳費足夠,我就帶你走遍RRR城。

小z很開心,直接就把錢一次性繳足了。然而小z心機很重,他想選擇的路程儘量長。

然而司機也很聰明,他每次從一個點走到另外一個點的時候都走最短路徑。

你能幫幫小z嗎?

需要保證這三個旅行景點一個作為起點,一個作為中轉點一個作為終點。(一共三個景點,並且需要保證這三個景點不能重複).

輸入描述:

本題包含多組輸入,第一行輸入一個整數t,表示測試資料的組數
每組測試資料第一行輸入兩個數N,M表示RRR城一共有的旅遊景點的數量,以及RRR城中有的路的數量。
接下來M行,每行三個數,a,b,c表示從a景點和b景點之間有一條長為c的路
t<=40
3<=N,M<=1000
1<=a,b<=N
1<=c<=100

輸出描述:

每組資料輸出兩行,
每組資料包含一行,輸出一個數,表示整條路程的路長。
如果找不到可行解,輸出-1.

思路:

遍歷中轉點,找出和中轉點距離最大的兩個地方分別作為起點和終點。

我選擇了鏈式前向星+dij

鏈式前向星遍歷時採用

for(int i=head[u];i;i=edge[i].next){
}
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define DOF 0x7f7f7f7f
#define endl '\n'
#define mem(a,b) memset(a,b,sizeof(a))
#define debug(case,x); cout<<case<<"  : "<<x<<endl;
#define open freopen("ii.txt","r",stdin)
#define close freopen("oo.txt","w",stdout)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<long long,long long> PII;
const int maxn = 2e5 + 10;
int n,m;
int dis[maxn],vis[maxn];
priority_queue<pii,vector<pii >,greater<pii> >qp;
struct edge{
    int next;
    int to;
    int val;
}edge[maxn];
int head[maxn];
int tot=0;
void add(int u,int v,int val){
    edge[++tot].to=v;
    edge[tot].val=val;
    edge[tot].next=head[u];
    head[u]=tot;
}

int dij(int src){
    while(!qp.empty())qp.pop();
    for(int i=1;i<=n;++i){
        dis[i]=INF;vis[i]=0;
    }
    dis[src]=0;
    qp.push({0,src});
    int x=0,y=0;
    while(!qp.empty()){
        pii t=qp.top();qp.pop();
        int u=t.second;
        if(vis[u])continue;
        vis[u]=1;
        y=max(y,dis[u]);
        if(y>x)swap(x,y);
        for(int i=head[u];i;i=edge[i].next){
            if(vis[edge[i].to])continue;
            if(dis[edge[i].to]>dis[u]+edge[i].val){
                dis[edge[i].to]=dis[u]+edge[i].val;
                qp.push({dis[edge[i].to],edge[i].to});
            }
        }
    }
    if(!y)return 0;
    else return x+y;
}

int main(){
    int t;cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;++i)head[i]=-1;
        int a,b,c;
        while(m--){
            cin>>a>>b>>c;
            add(a,b,c);add(b,a,c);
        }
        int ans=-1;
        for(int i=1;i<=n;++i){
            ans=max(dij(i),ans);
        }
        if(ans)cout<<ans<<endl;
        else cout<<-1<<endl;

    }
}