【GDKOI2012模擬02.01】探險(最短路&&SPFA)

Description

這裏寫圖片描述

Solution

這裏暴力都能過!!!
先不過這些。
我們要找一條路徑出來,首先肯定是過1號節點連出去的邊的。
我們可以枚舉這個邊,然後求出起點不經過這條邊的最短路徑到達j,然後再加上這條邊的權值。
怎麼算不經過這條邊的最短路徑呢?
我們可以維護最短路徑和次短路徑,如果這條邊被最短路徑包括了,那麼就走次短路徑,否則直接走最短路徑。但是我們要保證最短路徑的出邊和次短路徑的出邊不相等(出邊就是起點走出來的第一條邊),否則可能會把出邊重複走,因爲最短如果包含出邊的話,那麼出邊就是枚舉的那條邊,次短路明顯不能包含這條邊。
維護最短和次短,且要求出邊不同實際上很簡單。用最短更新最短,最短更新次短,次短更新次短。

Code

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=2e5+7;
int i,j,k,l,t,n,m,ans,x,y,u,v,r,mid;
int first[maxn*2],last[maxn*2],next[maxn*2],chang[maxn*2],num,fan[maxn*2];
int d[maxn],cd[maxn],dy[maxn],cdy[maxn],data[maxn];
bool bz[maxn*2];
void add(int x,int y,int z,int u){
    last[++num]=y,next[num]=first[x],first[x]=num,chang[num]=z;fan[num]=num+1;
    last[++num]=x,next[num]=first[y],first[y]=num,chang[num]=u;fan[num]=num-1;
}
void spfa(){
    int head=0,tail=1,i,j,now;data[1]=1;
    memset(d,127,sizeof(d));memset(cd,127,sizeof(cd));d[1]=0;bz[1]=1;
    while(head<tail){
        now=data[++head];
        rep(i,now){
            if(d[last[i]]>d[now]+chang[i]){
                d[last[i]]=d[now]+chang[i];dy[last[i]]=dy[now];
                if(now==1)dy[last[i]]=i;
                if(!bz[last[i]]){
                    bz[last[i]]=1;
                    data[++tail]=last[i];
                }
            }
            else if(cd[last[i]]>d[now]+chang[i]&&dy[now]!=dy[last[i]]&&fan[dy[now]]!=dy[last[i]]&&last[i]!=1){
                cd[last[i]]=d[now]+chang[i];cdy[last[i]]=dy[now];
                if(now==1)cdy[last[i]]=i;
                if(!bz[last[i]]){
                    bz[last[i]]=1;
                    data[++tail]=last[i];
                }
            }
            if(cd[last[i]]>cd[now]+chang[i]&&cdy[now]!=dy[last[i]]&&fan[cdy[now]]!=dy[last[i]]&&last[i]!=1){
                cd[last[i]]=cd[now]+chang[i];cdy[last[i]]=cdy[now];
                if(now==1)cdy[last[i]]=i;
                if(!bz[last[i]]){
                    bz[last[i]]=1;
                    data[++tail]=last[i];
                } 
            }
        }
        bz[now]=0;
    }
}
int main(){
//  freopen("fan.in","r",stdin);
    scanf("%d%d",&n,&m);
    fo(i,1,m)scanf("%d%d%d%d",&x,&y,&u,&v),add(x,y,u,v),r+=max(u,v);
    spfa();ans=0x7fffffff;
    rep(i,1){
        if(d[last[i]]!=d[1]+chang[i]){
            ans=min(ans,d[last[i]]+chang[fan[i]]);
        }
        else ans=min(ans,cd[last[i]]+chang[fan[i]]);
    }
    printf("%d\n",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章