zoukankan      html  css  js  c++  java
  • Tyvj1293(新姿势:次短路)

    题目链接

    分析:
    我一开始想了一个自己都可以hack掉的算法:
    先来一个朴素spfa
    之后循环与终点相连的所有边,
    到达终点的距离就是dis[way[i].y]+way[i].v
    统计最小的路径和次小的路径,输出答案
    竟然过掉了6个点

    然后我就暴力搜索,T了7个点,STO

    好,我们来正经的
    于是我又想了一个做法,每个点都统计一下到达该点的最小距离和次小距离
    但这好像不大现实

    后来我才发现,这是一道次短路的裸题
    又可以学习一种新算法了

    具体的做法引用一下BYVOID大牛文章里的一段话:
    我们要对一个有向赋权图(无向图每条边可以看作两条相反的有向边)
    的顶点S到T之间求次短路径,首先应求出S的单源最短路径
    遍历有向图,标记出可以在最短路径上的边,加入集合K
    然后枚举删除集合K中每条边,求从S到T的最短路径,
    记录每次求出的路径长度值,其最小值就是次短路径的长度
    在这里我们认为次短路径长度可以等于最短路径长度,
    如果相等,也可以看作是从S到T有不止一条最短路径
    如果我们规定求从S到T**大于最短路径长度**的次短路径,
    则答案就是每次删边后大于原最短路径的S到T的最短路径长度的最小值

    成功AC

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    
    using namespace std;
    
    const int INF=0x33333333;
    const int N=10001;
    int s,t,n,m;
    struct node{
        int x,y,nxt,v;
    };
    node way[N<<2];
    int st[N],tot=0,ans1,ans2,dis[N],q[N],tou,wei,pre[N];
    bool p[N];
    
    void add(int u,int w,int z)
    {
        tot++;
        way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
        tot++;
        way[tot].x=w;way[tot].y=u;way[tot].v=z;way[tot].nxt=st[w];st[w]=tot;
    }
    
    int spfa(int s,int t)
    {
        tou=wei=0;
        q[++wei]=s;
        memset(pre,0,sizeof(pre));
        memset(dis,0x33,sizeof(dis));
        dis[s]=0;
        memset(p,1,sizeof(p));
        p[s]=0;
        do
        {
            int r=q[++tou];
            for (int i=st[r];i;i=way[i].nxt)
            {
                if (dis[way[i].y]>dis[r]+way[i].v)
                {
                    dis[way[i].y]=dis[r]+way[i].v;
                    pre[way[i].y]=i;
                    if (p[way[i].y])
                    {
                        q[++wei]=way[i].y;
                        p[way[i].y]=0;
                    }
                }
            }
            p[r]=1;
        }
        while (tou<wei);
        return dis[t];
    }
    
    int spfa2(int s,int t)
    {
        tou=wei=0;
        q[++wei]=s;
        memset(dis,0x33,sizeof(dis));
        dis[s]=0;
        memset(p,1,sizeof(p));
        p[s]=0;
        do
        {
            int r=q[++tou];
            for (int i=st[r];i;i=way[i].nxt)
            {
                if (dis[way[i].y]>dis[r]+way[i].v)
                {
                    dis[way[i].y]=dis[r]+way[i].v;
                    if (p[way[i].y])
                    {
                        q[++wei]=way[i].y;
                        p[way[i].y]=0;
                    }
                }
            }
            p[r]=1;
        }
        while (tou<wei);
        return dis[t];
    }
    
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for (int i=1;i<=m;i++)
        {
            int u,w,z;
            scanf("%d%d%d",&u,&w,&z);
            add(u,w,z);
        }
        ans1=spfa(s,t);
        if (ans1==INF) {
            printf("He lose his love
    ");
            return 0;
        }
        ans2=INF;
        for (int i=t;i!=s;i=way[pre[i]].x)   //记录最短路 
        {
            int u=way[pre[i]].v;
            way[pre[i]].v=INF;
            ans2=min(ans2,spfa2(s,t));
            way[pre[i]].v=u;   //别忘了恢复值 
        }
        if (ans2==INF) printf("He will be cursed
    ");
        else printf("%d
    ",ans2);
        return 0;   
    }
  • 相关阅读:
    Coding Souls团队第二阶段冲刺(三)
    Coding Souls团队第二阶段冲刺(二)
    第一阶段意见评价
    PHPMailer/PHPMailer的使用
    使用jquery.media.js实现pdf在线预览
    select2(前端选择框_框架)
    安装Docker CE+阿里云镜像仓库
    docker学习
    前端开发框架WeUI
    php _Markdown转HTML
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673234.html
Copyright © 2011-2022 走看看