标签:
对于30%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。
以s1,t1,s2,t2为源点分别跑spfa ,记录下单源最短路,然后通过 f[u]+len[u,v]+g[v]=len的方式把所有在两个人最短路上的公共边加入有向无环图,然后利用拓扑排序求出最长链即为答案。
因为可能存在路径方向的问题,所有我们把s2,t2反过来再计算一边,就可以了 。
附样例一组:(可以卡掉某些AC程序)
8 6
1 7 3 8
1 2 1
1 4 1
4 8 1
2 3 1
2 7 3
4 7 3 output: 1
有些程序把1 7 3 8 改成3 8 1 7 出的答案会不一样
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define N 2000 using namespace std; int n,m,s1,t1,s2,t2,len1,len2,ans; int f1[N],g1[N],f2[N],g2[N],can[N],ins[N],q[N]; int point[N],next[1000000],v[1000000],len[1000000],tot,cnt; int point1[N],next1[1000000],v1[1000000],c[1000000]; int maxn[N],f[N]; void insert(int x,int y,int z) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; len[tot]=z; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; len[tot]=z; } void add(int x,int y,int z) { cnt++; next1[cnt]=point1[x]; point1[x]=cnt; v1[cnt]=y; c[cnt]=z; } void spfa(int *dis,int s) { memset(can,0,sizeof(can)); dis[s]=0; can[s]=1; queue<int> p; p.push(s); while (!p.empty()) { int now=p.front(); p.pop(); for (int i=point[now];i;i=next[i]) if (dis[v[i]]>dis[now]+len[i]) { dis[v[i]]=dis[now]+len[i]; if (can[v[i]]==0) { can[v[i]]=1; p.push(v[i]); } } can[now]=0; } } void solve() { memset(f,0,sizeof(f)); int head=0,tail=0; for (int i=1;i<=n;i++) if (!ins[i]) q[++tail]=i; while (head<tail) { int now=q[++head]; for (int i=point1[now];i;i=next1[i]) { f[v1[i]]=f[now]+c[i]; if (!--ins[v1[i]]) q[++tail]=v1[i]; } } for (int i=1;i<=n;i++) ans=max(ans,f[i]); } int main() { scanf("%d%d",&n,&m); scanf("%d%d%d%d",&s1,&t1,&s2,&t2); for (int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); insert(x,y,z); } memset(f1,0x7f,sizeof(f1)); memset(g1,0x7f,sizeof(g1)); memset(f2,0x7f,sizeof(f2)); memset(g2,0x7f,sizeof(g2)); spfa(f1,s1); len1=f1[t1]; spfa(g1,t1); spfa(f2,s2); len2=f2[t2]; spfa(g2,t2); for (int i=1;i<=n;i++) for (int j=point[i];j;j=next[j]) if (f1[i]+len[j]+g1[v[j]]==len1&&f2[i]+len[j]+g2[v[j]]==len2) add(i,v[j],len[j]),ins[v[j]]++; solve(); memset(f2,0x7f,sizeof(f2)); memset(g2,0x7f,sizeof(g2)); spfa(f2,t2); spfa(g2,s2); cnt=0; memset(ins,0,sizeof(ins)); memset(point1,0,sizeof(point1)); memset(next1,0,sizeof(next1)); for (int i=1;i<=n;i++) for (int j=point[i];j;j=next[j]) if (f1[i]+len[j]+g1[v[j]]==len1&&f2[i]+len[j]+g2[v[j]]==len2) add(i,v[j],len[j]),ins[v[j]]++; solve(); printf("%d\n",ans); }
bzoj 1880: [Sdoi2009]Elaxia的路线(拓扑排序+spfa)
标签:
原文地址:http://blog.csdn.net/clover_hxy/article/details/51353911