• P3106 [USACO14OPEN]GPS的决斗(最短路)


     化简:够简的了.....但是!翻译绝对有锅。

    这个最短路是从n到每个点的单源最短路,也就是最短路径树。

    那么,思路就很明确了。建两个图,然后跑两边SPFA,记录下最短路径。

    然后,对于两点之间的边,如果最短路不经过它,那么最终图边权+1;

    然后在最终图上(边权为0,1,2)跑一遍SPFA即可。

    一开始我想复杂了,在想怎么记录路径,怎么重构图.balabala。

    然后发现,怎么才能让两点不在最短路径上呢?

    SPFA的松弛操作,依据是三角不等式。于是,如果两点之间的最短路的距离如果不等于边权(也就是最短路径不过它俩之间的边)那么就它就是一条会报警的边。

    $$看来SPFA最重要的是三角不等式$$

    于是,只要暴力跑三遍SPFA即可。

    用尽浑身解数,信仰SPFA,各种常数优化,读入挂,我还是没能跑到最优解的第一面....在第二页前几个徘徊.....

    代码:(这么长的图论题也不多见,但是好像逛公园就那么长)

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define rg register
    using namespace std;
    const int maxn=1e6+10;
    int n,m;
    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;
    }e1[maxn],e2[maxn],e[maxn];
    int head[maxn],head1[maxn],head2[maxn];
    int cnt1,cnt2,cnt;
    inline void addedge1(int from,int to,int dis)
    {
        e1[++cnt1].next=head1[from];
        e1[cnt1].to=to;
        e1[cnt1].dis=dis;
        head1[from]=cnt1;
    }
    inline void addedge2(int from,int to,int dis)
    {
        e2[++cnt2].next=head2[from];
        e2[cnt2].to=to;
        e2[cnt2].dis=dis;
        head2[from]=cnt2;
    }
    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 dis1[maxn],vis1[maxn],pre1[maxn];
    struct cmp1
    {
        bool operator () (int a,int b)
        {
            return dis1[a]>dis1[b];
        }
    };
    inline void spfa1()
    {
        priority_queue < int , vector < int > , cmp1 > q;
        for(rg int i=1;i<=n;i++)
        {
            dis1[i]=2147483647;
            vis1[i]=0;
        }
        q.push(n);
        dis1[n]=0;
        vis1[n]=1;
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            vis1[u]=0;
            for(rg int i=head1[u];i;i=e1[i].next)
            {
                int v=e1[i].to;
                if(dis1[v]>dis1[u]+e1[i].dis)
                {
                    dis1[v]=dis1[u]+e1[i].dis;
                    if(vis1[v]==0)
                    {
                        vis1[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    int dis2[maxn],vis2[maxn],pre2[maxn];
    struct cmp2
    {
        bool operator () (int a,int b)
        {
            return dis2[a]>dis2[b];
        }
    };
    inline void spfa2()
    {
        priority_queue < int , vector < int > , cmp2 > q;
        for(rg int i=1;i<=n;i++)
        {
            dis2[i]=2147483647;
            vis2[i]=0;
        }
        q.push(n);
        dis2[n]=0;
        vis2[n]=1;
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            vis2[u]=0;
            for(rg int i=head2[u];i;i=e2[i].next)
            {
                int v=e2[i].to;
                if(dis2[v]>dis2[u]+e2[i].dis)
                {
                    dis2[v]=dis2[u]+e2[i].dis;
                    if(vis2[v]==0)
                    {
                        vis2[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    int dis[maxn],vis[maxn];
    struct cmp
    {
        bool operator () (int a,int b)
        {
            return dis[a]>dis[b];
        }
    };
    inline void rebuild()
    {
        for(rg int i=1;i<=n;i++)
        {
            for(int j=head1[i];j;j=e1[j].next)
            {
                int v1=e1[j].to;
                int v2=e2[j].to;
                //cout<<i<<' '<<v1<<endl;
                int d=0;
                if(dis1[v1]-dis1[i]!=e1[j].dis)
                d++;
                if(dis2[v2]-dis2[i]!=e2[j].dis)
                d++;
                addedge(v1,i,d);
            }
        }
    }
    inline void spfa()
    {
        priority_queue < int , vector < int > , cmp > q;
        for(rg int i=1;i<=n;i++)
        {
            dis[i]=2147483647;
            vis[i]=0;
        }
        q.push(1);
        dis[1]=0;
        vis[1]=1;
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            vis[u]=0;
            for(rg 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)
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    int main()
    {
        n=read();
        m=read();
        for(rg int i=1;i<=m;i++)
        {
            int a=read(),b=read(),c=read(),d=read();
            //scanf("%d%d%d%d",&a,&b,&c,&d);
            addedge1(b,a,c);
            addedge2(b,a,d);
            //addedge(a,b,0);
        }
        spfa1();
        spfa2();
        rebuild();
        spfa();
        printf("%d",dis[n]);
        return 0;
    }

    (完)

  • 相关阅读:
    ad域的那些事儿
    关于vs无法创建虚拟目录的问题
    关于Java链接c#的webapi的注意事项
    创建.net framework webapi出现“Web 服务器被配置为不列出此目录的内容。”错误
    vs2017专业版和企业版的密钥
    数据库‘master’中拒绝CREATE DATABASE权限
    vue局部路由守卫使用
    记一次关于vantUI 下拉列表list加载数据的问题
    vue中使用require动态拼接img路径
    记录一次关于el-tree中让内容与左边有距离的爬坑记录
  • 原文地址:https://www.cnblogs.com/ajmddzp/p/11780356.html
Copyright © 2020-2023  润新知