1. 程式人生 > >『USACO』安全路經Travel (bzoj 1576)

『USACO』安全路經Travel (bzoj 1576)

路徑 using 原來 int main tmp cmp set info

題目鏈接

題目描述

技術分享圖片



解題思路

沒啥思路。

首先能想到要做一遍SPFA(堆優化),順便記錄一下每個點的最短路是由哪個邊來的。

顯然,1到所有的點的最短路組成了一棵樹,但是接下來就不知道咋做了2333333。

我們發現:因為不能從原來的路徑過來,所以我們要選擇另一條路,也就將終點和另外的一個節點連接達到最短路,我們仔細想想,我們構造的最短路樹已經滿足了每個點到1號點的距離最近,所以從別的點轉移過來一定能得到最近的距離。

先睡覺,明天再寫qwq??



代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=100050;
const int maxm=200050;
int n,m,cnt=0,tot=0;
int head[maxm<<1],ne[maxm<<1],to[maxm<<1],v[maxm<<1],a[maxm],b[maxm],c[maxm];
bool flag[maxm<<1];
int dis[maxn],from[maxn],fa[maxn],num[maxn],ans[maxn];
bool vis[maxn];
struct nod{
    int x;
};
struct edge{
    int f,t,val;
};
edge e[maxm<<1];
inline bool operator < (nod a,nod b){
    return dis[a.x]>dis[b.x];
}
inline void add(int f,int t,int val){
    ne[++cnt]=head[f],head[f]=cnt,to[cnt]=t,v[cnt]=val;
}
inline void ini(){
    memset(ans,-1,sizeof(ans));
    for(register int i=0;i<maxn;i++)fa[i]=i;
}
inline int getfa(int x){
    return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
inline bool cmp(edge a,edge b){
    return a.val<b.val;
}
inline void spfa(){
    priority_queue<nod>q;
    memset(dis,0x3f,sizeof(dis));
    vis[1]=1,dis[1]=0;
    q.push((nod){1});
    while(!q.empty()){
        nod x=q.top();
        q.pop();
        vis[x.x]=0;
        for(register int i=head[x.x];i;i=ne[i]){
            if(dis[to[i]]>dis[x.x]+v[i]){
                dis[to[i]]=dis[x.x]+v[i];
                from[to[i]]=x.x;
                num[to[i]]=i;
                if(!vis[to[i]]){
                    vis[to[i]]=1;
                    q.push((nod){to[i]});
                }
            }
        }
    }
}
int main(){
    ini();
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=m;i++){
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        add(a[i],b[i],c[i]),add(b[i],a[i],c[i]);
    }
    spfa();
    for(register int i=2;i<=n;i++){
        int tmp=num[i];
        if(num[i]&1)tmp++;
        else tmp--;
        flag[num[i]]=flag[tmp]=1;
    }
    for(register int i=1;i<=m;i++){
        if(flag[i<<1])continue;
        e[++tot]=(edge){a[i],b[i],dis[a[i]]+dis[b[i]]+c[i]};
    }
    sort(e+1,e+tot+1,cmp);
    for(register int i=1;i<=tot;i++){
        int f=e[i].f,t=e[i].t;
        f=getfa(f),t=getfa(t);
        while(f!=t){
            if(dis[f]<dis[t])swap(f,t);
            ans[f]=e[i].val-dis[f];
            fa[f]=from[f];
            f=getfa(f);
        }
    }
    for(register int i=2;i<=n;i++){
        printf("%d\n",ans[i]);
    }
}

『USACO』安全路經Travel (bzoj 1576)