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; }
以上是关于BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1880 [Sdoi2009]Elaxia的路线(最短路+拓扑序)
[BZOJ1880] [Sdoi2009] Elaxia的路线 (SPFA & 拓扑排序)
bzoj 1880: [Sdoi2009]Elaxia的路线spfa+拓扑排序