Luogu P2149 [SDOI2009]Elaxia的路线
一看是purple题很怂。。。我太弱了。。。
但是在这个块里面得再刷一题,
另两题一题是差分,一题是网络流(还是我并不知道是什么的最小割。。。)
出于lazy的原因并不想学习差分和最小割(并学不会)
又回到了此题,认真看了一遍,
觉得SPFA再枚举两个最短路中的所有边看公共边就好了吧。。。
可是如果有不同的最短路呢,如果有特别多不同的最短路呢
那。。。该怎么实现呢 那。。。我就不会了啊
又继续想,从模拟样例开始,我觉得最短路中的公共路应该连在一起吧,开头一条边,中间两条边是不会有的
这样又怎么样呢,怎么样呢。。。
give up–>看题解
公共路还真是连在一起的!
SPFA没错,然后的做法有拓扑和dp等等
我选择开始打最友善(只看得懂)的一种解法,
spfa*4 —>对最短路上的边再建图—>建完图找最长链
并且认识到了一种判断边是否在最短路上的方法
如果st到x的距离+x,y之间距离+y到ed之间距离 那么x->y这条边在最短路上
#include<cstdio>
#include<cstring>
int n,m,s1,e1,s2,e2,len,lenn,ans=0;
struct nod1{int x,y,c,next;}a[1000100],a2[1000100];
//。。。试了好几次才开对了空间,空间还是算不准。。。
int first[3100],ffirst[3100],max[3100],b[3100];
int road1[3100],road2[3100],road3[3100],road4[3100];
int ins(int x,int y,int c)
{//第一次建图 spfa)
len++;
a[len].x=x;
a[len].y=y;
a[len].c=c;
a[len].next=first[x];
first[x]=len;
}
int inss(int x,int y,int c)
{//第二次建图 搜索)
lenn++;
a2[lenn].x=x;
a2[lenn].y=y;
a2[lenn].c=c;
a2[lenn].next=ffirst[x];
ffirst[x]=lenn;
}
int spfa(int st,int *road)
{
int tou=1,wei=2;
int f[10010];
f[tou]=st;
road[st]=0;
memset(b,0,sizeof(b));
b[st]=1;
while(tou<wei)
{
int x=f[tou];
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(road[y]>road[x]+a[i].c)
{
road[y]=road[x]+a[i].c;
if(b[y]==0)
{
b[y]=1;
f[wei]=y;
wei++;
}
}
}
b[x]=0;
tou++;
}
}
int find(int x)
{//搜索找最长链
if(max[x]!=0)return max[x];
for(int i=ffirst[x];i;i=a2[i].next)
{
int y=a2[i].y,z=a2[i].c;
if(find(y)+z>max[x])
{
max[x]=max[y]+z;
}
}
return max[x];
}
int buildpic()
{
for(int i=1;i<=len;i++)
{
int x=a[i].x,y=a[i].y,z=a[i].c;
if(((road1[x]+z+road2[y]==road1[e1])&&(road3[x]+z+road4[y]==road3[e2]))
||((road1[y]+z+road2[x]==road1[e1])&&(road3[x]+z+road4[y]==road3[e2])))
{
inss(x,y,z);//printf("!!!!! ");
}
}
}
int main()
{
scanf("%d %d",&n,&m);
scanf("%d %d %d %d",&s1,&e1,&s2,&e2);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
ins(x,y,z);ins(y,x,z);
}
memset(road1,63,sizeof(road1));
memset(road2,63,sizeof(road2));
memset(road3,63,sizeof(road3));
memset(road4,63,sizeof(road4));
//4*spfa
spfa(s1,road1);
spfa(e1,road2);
spfa(s2,road3);
spfa(e2,road4);
//printf("%d %d ",road1[e1],road3[e2]);
buildpic();//建图
for(int i=1;i<=n;i++)
{
if(max[i]==0)
{
//printf("11111111");
find(i);
//printf("222222222");
}//printf("1111");
if(max[i]>ans)ans=max[i];
}
printf("%d",ans);
}
在RE了3次后终于A了 这个块终于过la 以后要注意空间