首页 > 代码库 > BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序

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

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

题解:

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

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

技术分享
#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>#include <deque>using namespace std;#define INF 6666666const 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的路线 最短路+拓扑排序