大家都说这是一道大水题。。。想打dyx
应该了解到拓扑排序的功能,类比于食物链那道题,拓扑排序可以dp求出最长链。而在这道题只需求出可以重复的部分搞一个拓扑排序即可。
而怎样求重复的部分呢?有一个思想很好:将一条线路拆分成起点到此的距离和终点到此的距离,跑两遍单源最短路,然后类似地枚举求出一些可以重复的路径,Topo一下就好了
(尝试新代码风格2333,bz会卡空间,实测将边的数量开小一半就可以过了)
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1501;
struct edge
{
int from,to,next,val;
}oe[maxn*maxn>>1],nowe[maxn*maxn>>1];
int n,ocnt,nowcnt,ans,m,S1,S2,T1,T2;
int ohead[maxn],nowhead[maxn],f[maxn],degree[maxn];
int dists1[maxn],dists2[maxn],distt1[maxn],distt2[maxn];
bool vst[maxn];
void insert(int &cnt,int head[],edge e[],int from,int to,int val)
{
e[++cnt].from=from;e[cnt].to=to;e[cnt].val=val;e[cnt].next=head[from];head[from]=cnt;
}
void spfa(int S,int head[],edge e[],int dist[])
{
queue<int>q;
memset(dist+1,0x3f,sizeof(int)*n);
memset(vst+1,0,sizeof(bool)*n);
q.push(S);
vst[S]=true;dist[S]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vst[u]=false;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(dist[u]+e[i].val<dist[v])
{
dist[v]=dist[u]+e[i].val;
if(!vst[v])vst[v]=true,q.push(v);
}
}
}
}
void Topological_sort(int head[],edge e[])
{
memset(f+1,0,sizeof(int)*n);
queue<int>q;
for(int i=1;i<=n;i++)
if(!degree[i])q.push(i);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
f[v]=max(f[v],f[u]+e[i].val);
ans=max(ans,f[v]);
degree[v]--;
if(!degree[v])q.push(v);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&S1,&T1,&S2,&T2);
for(int i=1,u,v,val;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&val);
insert(ocnt,ohead,oe,u,v,val);
insert(ocnt,ohead,oe,v,u,val);
}
spfa(S1,ohead,oe,dists1);
spfa(T1,ohead,oe,distt1);
spfa(S2,ohead,oe,dists2);
spfa(T2,ohead,oe,distt2);
for(int i=1;i<=ocnt;i++)
if(dists1[oe[i].from]+oe[i].val+distt1[oe[i].to]==dists1[T1])
if(dists2[oe[i].from]+oe[i].val+distt2[oe[i].to]==dists2[T2])
insert(nowcnt,nowhead,nowe,oe[i].from,oe[i].to,oe[i].val),degree[oe[i].to]++;
Topological_sort(nowhead,nowe);
memset(nowhead+1,0,sizeof(int)*n);
memset(degree+1,0,sizeof(int)*n);
nowcnt=0;
for(int i=1;i<=ocnt;i++)
if(dists1[oe[i].from]+oe[i].val+distt1[oe[i].to]==dists1[T1])
if(distt2[oe[i].from]+oe[i].val+dists2[oe[i].to]==distt2[S2])
insert(nowcnt,nowhead,nowe,oe[i].from,oe[i].to,oe[i].val),degree[oe[i].to]++;
Topological_sort(nowhead,nowe);
cout<<ans;
return 0;
}