对于30%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。
思路题--SPFA+拓扑排序求最长链
首先用两个起点和两个终点分别做一次SPFA,求出他们到图中其他所有点的最短路径。
然后枚举图中每一条边,判断他是否同时在两个人的最短路上,即这条边的权值加上他的端点到两人起点和终点的距离是否恰好等于起点到终点的最短距离。
如果在的话,就加入到新图中。
问题就变成了求新图的最长链,直接topsort即可。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <queue> #define M 1500+5 #define inf 0x3f3f3f3f using namespace std; queue<int> q; int n,m; int du[M],d[M],H[M],inq[M],h[M],tot,Tot,s1[M],s2[M],t1[M],t2[M]; struct edge { int x,y,v,ne; }e[1000000],E[1000000]; void Addedge(int x,int y,int v) { e[++tot].y=y; e[tot].x=x; e[tot].ne=h[x]; e[tot].v=v; h[x]=tot; } void Add(int x,int y,int v) { E[++Tot].y=y; E[Tot].v=v; E[Tot].ne=H[x]; H[x]=Tot; du[y]++; } void Spfa(int s,int d[]) { for (int i=1;i<=n;i++) d[i]=inf,inq[i]=0; d[s]=0,inq[s]=1; q.push(s); while (!q.empty()) { int x=q.front(); q.pop(); inq[x]=0; for (int i=h[x];i;i=e[i].ne) { int y=e[i].y; if (d[y]>d[x]+e[i].v) { d[y]=d[x]+e[i].v; if (!inq[y]) q.push(y),inq[y]=1; } } } } void Topsort() { for (int i=1;i<=n;i++) { d[i]=0; if (!du[i]) q.push(i); } int ans=0; while (!q.empty()) { int x=q.front(); q.pop(); for (int i=H[x];i;i=E[i].ne) { int y=E[i].y; d[y]=max(d[y],d[x]+E[i].v); ans=max(ans,d[y]); du[y]--; if (!du[y]) q.push(y); } } printf("%d\n",ans); } int main() { int x1,x2,y1,y2; scanf("%d%d",&n,&m); scanf("%d%d%d%d",&x1,&y1,&x2,&y2); for (int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); Addedge(x,y,v); Addedge(y,x,v); } Spfa(x1,s1); Spfa(y1,t1); Spfa(x2,s2); Spfa(y2,t2); for (int i=1;i<=tot;i+=2) { int x=e[i].x,y=e[i].y,v=e[i].v; int k1=min(s1[x],s1[y])+min(t1[y],t1[x])+v,k2=min(s2[x],s2[y])+min(t2[x],t2[y])+v; if (k1==s1[y1]&&k2==s2[y2]) { if (s1[x]<s1[y]) Add(x,y,v); else Add(y,x,v); } } Topsort(); return 0; }
【BZOJ 1880】 [Sdoi2009]Elaxia的路线
原文地址:http://blog.csdn.net/regina8023/article/details/44832323