BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序

Posted WDZRMPCBIT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序相关的知识,希望对你有一定的参考价值。

题意:给定两个点对和一张无向图,求两个点对的最短路中,重边边权和的最大值

题解:

首先从给出的四个点出发跑出到其他所有点的最短路,然后判断哪些边是重边。找出所有重边后,将其构有向图,在该图上用拓扑排序求最长路。

开始的时候枚举每一条边我没有建反向边,而是每次判定的时候互换一下边的始末点看是否合法,结果最后一个点死活过不去。后来上网搜题解才知道,必须建反向边,与原边分别判断。果然偷懒就是不行啊……

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <deque>
using namespace std;
#define INF 6666666

const int MAXN=1500+2;
const int MAXM=300000+2;
struct Hash{
    int u,w;
    Hash *Next;
    Hash(){}
    Hash(int _u,int _w,Hash *_Next):u(_u),w(_w),Next(_Next){}
}*Tab[2][MAXN],mem[6*MAXM];
int N,M,cnt[2],d[4][MAXN],c[MAXN],X1,Y1,X2,Y2,Ans;
bool Flag[MAXN];
deque<int> q;

void Insert(int t,int u,int v,int w){ Tab[t][u]=&(mem[cnt[t]++]=Hash(v,w,Tab[t][u]));}

void SPFA(int s,int *d){
    for(int i=1;i<=N;i++) d[i]=INF;
    d[s]=0,q.push_front(s);

    int x;
    while(!q.empty()){
        x=q.front(),q.pop_front();
        for(Hash *p=Tab[0][x];p;p=p->Next){
            if(d[p->u]<=d[x]+p->w) continue;
            d[p->u]=d[x]+p->w;
            if(Flag[p->u]) continue;
            Flag[p->u]=1;

            if(!q.empty() && d[p->u]<=d[q.front()]) q.push_front(p->u);
            else q.push_back(p->u);
        }
        Flag[x]=0;
    }
}

bool Check1(int u,int v,int w){
    if(d[0][u]+d[1][v]+w!=d[0][Y1]) return 0;
    if(d[2][u]+d[3][v]+w!=d[2][Y2]) return 0;
    return 1;
}

bool Check2(int u,int v,int w){
    if(d[0][u]+d[1][v]+w!=d[0][Y1]) return 0;
    if(d[2][u]+d[3][v]+w!=d[2][X2]) return 0;
    return 1;
}

int Topologic_Sort(){
    memset(d[2],0,sizeof(d[0]));
    for(int i=1;i<=N;i++)
        if(!c[i]) q.push_back(i);

    int x;
    while(!q.empty()){
        x=q.front(),q.pop_front();
        for(Hash *p=Tab[1][x];p;p=p->Next){
            c[p->u]--,d[2][p->u]=max(d[2][p->u],d[2][x]+p->w);
            if(!c[p->u]) q.push_back(p->u);
        }
    }

    int Ans=-1;
    for(int i=1;i<=N;i++) Ans=max(Ans,d[2][i]);
    return Ans;
}

int main(){
    cin >> N >> M >> X1 >> Y1 >> X2 >> Y2;
    for(int i=1,u,v,w;i<=M;i++){
        scanf("%d %d %d",&u,&v,&w);
        Insert(0,u,v,w),Insert(0,v,u,w);
    }

    SPFA(X1,d[0]),SPFA(Y1,d[1]),SPFA(X2,d[2]),SPFA(Y2,d[3]);
    for(int i=1;i<=N;i++)
        for(Hash *p=Tab[0][i];p;p=p->Next)
            if(Check1(i,p->u,p->w)) Insert(1,i,p->u,p->w),c[p->u]++;
    Ans=Topologic_Sort();

    SPFA(Y2,d[2]),SPFA(X2,d[3]);
    memset(Tab[1],0,sizeof(Tab[1]));
    for(int i=1;i<=N;i++)
        for(Hash *p=Tab[0][i];p;p=p->Next)
            if(Check2(i,p->u,p->w)) Insert(1,i,p->u,p->w),c[p->u]++;
    cout << max(Ans,Topologic_Sort()) << endl;

    return 0;
}
View Code

 

以上是关于BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1880 [Sdoi2009]Elaxia的路线(最短路+拓扑序)

BZOJ1880: [Sdoi2009]Elaxia的路线

[BZOJ1880] [Sdoi2009] Elaxia的路线 (SPFA & 拓扑排序)

bzoj 1880: [Sdoi2009]Elaxia的路线spfa+拓扑排序

BZOJ1880: [Sdoi2009]Elaxia的路线|dijksrtra|暴力

BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序