P2149 Elaxia的路线
题意简述: 在一个n(n<=1500)个点的无向图里找两对点之间的最短路径的最长重合部分,即在保证最短路的情况下两条路径的最长重合长度(最短路不为一)
- 思路:
- 两边dij,第一遍最短路,第二遍在保证最短路的情况下让重合路径长度最长的先出队
- 代码:
#include <cstdio> #include <iostream> #include <queue> #include <cctype> #include <cstring> #include <algorithm> using namespace std; #define res register int inline int read() { int x=0,f=1; char ch; while(!isdigit(ch=getchar()))if(ch=='-')f=-1; while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } const int N=1500+10,M=N*N*2; int x1,y1,x2,y2,n,m,tot=1; struct node{ int x,y;//xΪ×î¶Ì·³¤¶È£¬yΪ×ÖغÏ·¾¶³¤¶È bool operator >(const node &n2) const{return x==n2.x?y<n2.y:x>n2.x;} bool operator <(const node &n2) const{return x==n2.x?y>n2.y:x<n2.x;}//СÓÚ ->¸üÓÅ node(int _x=0,int _y=0) : x(_x),y(_y){} bool operator ==(const node &n2) const{return x==n2.x&&y==n2.y;} node operator +(const node &n2) const{return node(x+n2.x,y+n2.y);} }edge[M],dis[M]; int ver[M],nxt[M],head[N],vis[N]; inline void add(int x,int y,int z) { ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; edge[tot]=node(z,0); } struct point{ int p; node d; bool operator <(const point &n2) const{return d>n2.d;} point(int _p=0,node _d=node(0,0)) : p(_p),d(_d) {} }; inline void dij(int s) { priority_queue <point> q; for(res i=1 ; i<=n ; ++i) dis[i]=node(0x3f3f3f3f,0),vis[i]=0; dis[s]=node(0,0); q.push(point(s,dis[s])); while(q.size()) { point now=q.top(); q.pop(); int x=now.p; if(vis[x]) continue; vis[x]=1; for(res i=head[x] ; i ; i=nxt[i]) { int y=ver[i]; if(dis[y]>dis[x]+edge[i]) { dis[y]=dis[x]+edge[i]; q.push(point(y,dis[y])); } } } } void dfs(int x) { for(res i=head[x] ; i ; i=nxt[i]) { int y=ver[i]; if(dis[y]+edge[i]==dis[x]) { edge[i].y+=edge[i].x; edge[i^1].y+=edge[i].x; dfs(y); } } } int main() { n=read(); m=read(); x1=read(); y1=read(); x2=read(); y2=read(); for(res i=1 ; i<=m ; ++i) { int x=read(),y=read(),z=read(); add(x,y,z); add(y,x,z); } dij(x1); dfs(y1); dij(x2); printf("%d ",dis[y2].y); return 0; }