zoukankan      html  css  js  c++  java
  • P4568 [JLOI2011]飞行路线(分层图)

    机房dalao推荐写的。。。(标签分层图)

    经过前几题的分层图的洗礼,我深刻地体会到了分层图的优点和好处(主要是不想打dp....)

    先说题吧....

    很明确,模型是最短路,但是,怎么跑k个,是个问题....

    解题过程:

    1、先跑最短路,记录路径,然后找路径上的k条最长边,删掉

    tips:贪心,很容易hack掉。

    2、建两层的分层图(以前打的都是两层居多)

    tips:会跑出0来....

    solution:

     主要就是:怎么连边喽....一开始老是卡住

    连边有2种情况:

    1. 同一层之间的边,边权为题目给的边权,同层之间连
    2. 层与层之间,一个点连到下一层的它对应的出点,边权为0,为单向边

    一共K层,上层可以跑到下层的出点,却不能回去,这就是一次免票。

    然后跑最短路,最后查t+n*k那个点的dis就可以了。

    for(int i=1;i<=m;i++)
        {
            int x,y,z;
            x=read();y=read();z=read();
            addedge(x,y,z);
            addedge(y,x,z);
            for(int j=1;j<=k;j++)
            {
                addedge(x+n*j,y+n*j,z);
                addedge(y+n*j,x+n*j,z);
                addedge(x+(j-1)*n,y+j*n,0);
                addedge(y+(j-1)*n,x+j*n,0);
            }
        }

    如上,分层连边。

    之后就是一个spfa的事了(然而我各种常数(畜生)优化+O2卡到比旁边dalao快600ms的地步哈哈哈哈)

    值得注意:

    1、最后要把每一层的t点连在一起,因为如果在第二层就跑到了最短,在最后一层的t并不能查到正确答案

    2、一共有k+1层,所以初始化dis要k+1层,因为这个卡了一小会...

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=6e6+10;
    int n,m,k;
    int s,t;
    inline int read()
    {
        int x=0,f=1;char s=getchar();
        while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    struct edge
    {
        int to,next,dis;
    }e[maxn];
    int head[maxn],cnt;
    inline void addedge(int from,int to,int dis)
    {
        e[++cnt].next=head[from];
        e[cnt].to=to;
        e[cnt].dis=dis;
        head[from]=cnt;
    }
    int dis[maxn],vis[maxn];
    struct cmp
    {
        bool operator () (int a,int b)
        {
            return dis[a]>dis[b];
        }
    };
    priority_queue < int , vector < int > , cmp > q;
    //queue < int > q;
    void spfa(int s)
    {
    
        for(int i=0;i<=(k+1)*n;i++)
        {
            dis[i]=2147483647;
            vis[i]=0;
        }
        //memset(dis,0x3f,sizeof(dis));
        q.push(s);
        dis[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
            //cout<<233;
            int u=q.top();
            //int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].dis)
                {
                    dis[v]=dis[u]+e[i].dis;
                    if(vis[v]==0)
                    {
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        n=read();
        m=read();
        k=read();
        s=read();
        t=read();
        for(int i=1;i<=m;i++)
        {
            int x,y,z;
            x=read();
            y=read();
            z=read();
            addedge(x,y,z);
            addedge(y,x,z);
            for(int j=1;j<=k;j++)
            {
                addedge(x+n*j,y+n*j,z);
                addedge(y+n*j,x+n*j,z);
                addedge(x+(j-1)*n,y+j*n,0);
                addedge(y+(j-1)*n,x+j*n,0);
            }
        }
        for(int i=1;i<=k;i++)
        addedge(t+(i-1)*n,t+i*n,0);
        spfa(s);
        cout<<dis[t+k*n];//printf("%d",dis[t+k*n]);
        return 0;
    }

    现在来说一说dp和分层图的关系:

    首先,分层图的“层”是什么,它就是dp中的状态。在一些图论题目中,状态不好转移,就可以使用分层图进行转移,不需要再管“从哪转移”这个问题,剩下的最优解直接交给spfa就行了。(最优贸易

    这些状态之间可以互相转移,一般在二维或是以上,可以省去一些不相关状态的枚举,但是因为spfa的广泛枚举性还是会枚举更多“不是最优解”的状态的。

    (完)

     

  • 相关阅读:
    SQL Server 2008R2中取得详细日期到毫秒级
    SQL Server Analysis Services无法启动
    SQL Server 2008R2编写脚本时智能提示功能丢失的处理
    SQL Server使用Linkserver连接Oracle
    好用的eclipse快捷键
    今天项目出现的问题总结
    8.2微信小页面问题总结
    SpringBoot整合rabbitmq
    初学Netty(杰哥好久不见)
    消息队列RabbitMQ学习
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11503135.html
Copyright © 2011-2022 走看看