题目大意:给定一张无向图,求s1到t1与s2到t2的最长公共最短路
以s1 t1 s2 t2为源做4次最短路
如果某条有向边满足s到起始点的距离+边长+终点到t的距离=s到t的最短路 那么这条边就可以在s到t的最短路上
我们把所有既在s1到t1的最短路上也在s2到t2的最短路上的有向边都拎出来
容易证明这个图一定没有环 因此拓扑排序求最长链即可
写完发现过不去样例。。。
因为这题题目描述与题意不符,两个人从不同方向走同一条边也算满足条件。。。
于是我们把s2和t2反转之后再做一遍即可。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1510 using namespace std; struct abcd{ int to,f,next; }table[M*M<<1]; int head[M],_head[M],tot; int n,m,s1,t1,s2,t2,ans; int f1[M],g1[M],f2[M],g2[M]; int degree[M]; void Add(int head[],int x,int y,int z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; } void SPFA(int f[],int S) { static int q[65540]; static bool v[M]; static unsigned short r,h; int i; memset(f,0x3f,sizeof(int)*M); f[S]=0;q[++r]=S; while(r!=h) { int x=q[++h];v[x]=false; for(i=head[x];i;i=table[i].next) if(f[table[i].to]>f[x]+table[i].f) { f[table[i].to]=f[x]+table[i].f; if(!v[table[i].to]) v[table[i].to]=true,q[++r]=table[i].to; } } } void Topology_Sort() { static int f[M],q[M]; int i,r=0,h=0; memset(f,0,sizeof f); for(i=1;i<=n;i++) if(!degree[i]) q[++r]=i; while(r!=h) { int x=q[++h]; ans=max(ans,f[x]); for(i=_head[x];i;i=table[i].next) { f[table[i].to]=max(f[table[i].to],f[x]+table[i].f); if(!--degree[table[i].to]) q[++r]=table[i].to; } } } int main() { int i,x,y,z; cin>>n>>m>>s1>>t1>>s2>>t2; for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); Add(head,x,y,z); Add(head,y,x,z); } SPFA(f1,s1); SPFA(g1,t1); SPFA(f2,s2); SPFA(g2,t2); for(x=1;x<=n;x++) for(i=head[x];i;i=table[i].next) if( g1[table[i].to]+table[i].f+f1[x]==f1[t1] && g2[table[i].to]+table[i].f+f2[x]==f2[t2] ) Add(_head,x,table[i].to,table[i].f),degree[table[i].to]++; Topology_Sort(); SPFA(f2,t2); SPFA(g2,s2); memset(_head,0,sizeof _head); for(x=1;x<=n;x++) for(i=head[x];i;i=table[i].next) if( g1[table[i].to]+table[i].f+f1[x]==f1[t1] && g2[table[i].to]+table[i].f+f2[x]==f2[s2] ) Add(_head,x,table[i].to,table[i].f),degree[table[i].to]++; Topology_Sort(); cout<<ans<<endl; return 0; }
时间: 2024-10-13 01:37:10