【GDKOI2012模拟02.01】探险(最短路&&SPFA)

Description

【GDKOI2012模拟02.01】探险(最短路&&SPFA)_第1张图片

Solution

这里暴力都能过!!!
先不过这些。
我们要找一条路径出来,首先肯定是过1号节点连出去的边的。
我们可以枚举这个边,然后求出起点不经过这条边的最短路径到达j,然后再加上这条边的权值。
怎么算不经过这条边的最短路径呢?
我们可以维护最短路径和次短路径,如果这条边被最短路径包括了,那么就走次短路径,否则直接走最短路径。但是我们要保证最短路径的出边和次短路径的出边不相等(出边就是起点走出来的第一条边),否则可能会把出边重复走,因为最短如果包含出边的话,那么出边就是枚举的那条边,次短路明显不能包含这条边。
维护最短和次短,且要求出边不同实际上很简单。用最短更新最短,最短更新次短,次短更新次短。

Code

#include
#include
#include
#include
#include
#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(headif(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);
}

你可能感兴趣的:(GDKOI,最短路)