Luogu P2149 [SDOI2009]Elaxia的路线

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 以后要注意空间

猜你喜欢

转载自blog.csdn.net/qq_42142540/article/details/80266582