• 2020/10/23 模拟赛 escape


    Description

    小恩听说有人想在邻国放置SD反导系统十分不满,为了做好应对导弹战的准备,小恩进行 了新的军队部署。 小恩的国家有 $n$个城市 $m$条无向道路,每条边长度都是正值。现在小恩想从$1$号城市向$n$ 号城市转移部分军队。由于这支部队已经多次执行了从$1$号城市到$n$号城市转移的任务,他们 己经走过了所有从$1$号到$n$号所有可能的最短路。为了迷惑敌国,小恩决定走剩下的路径中最 短的那一条简单路径,但又为了照顾到士兵的情绪,小恩要求这条路径如果经过了某些之前进行 从$1$到$n$的最短路转移时走过的道路,则这些道路必须按照原来的方向前进。现在问满足条件 的道路最短是多少。

    Solution

    图中要求一条有限制的次短路的长度

    有一个二进制分组的非正解方法

    给每一个点分配编号,设定集合$A_1,A_2, cdots ,A_{18}$,集合$B_1,B_2, cdots , B_{18}$,$A$集合表示在最短路上的编号第$i$位为0的点,$B$集合表示在最短路上的编号第$i$位为1的点

    如此操作可以使任意一对点至少在一种情况下分属$A$、$B$两个集合

    所以可以由$A$向$B$跑最短路,不经由最短路上的边,再由$B$向$A$重复一边

    只加入在最短路上的点是因为题目要求简单路径,若不如此可能会出现路径重叠

    实际上跑上几次正确率就已经非常高了,所以可以卡时

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<ctime>
    using namespace std;
    long long n,m,tot=1,head[100005],dist[100005],sdis[100005],tdis[100005],que[100005],top,A[100005],a,B[100005],b,ans=1<<30,len;
    bool vst[100005],ban[2000005],tag[100005];
    struct Edge
    {
        long long to,nxt,w,sta;
    }edge[2000005];
    queue<long long>q;
    inline long long read()
    {
        long long f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    void SPFA()
    {
        while(q.size())
        {
            long long u=q.front();
            q.pop();
            vst[u]=false;
            for(long long i=head[u];i;i=edge[i].nxt)
            {
                if(ban[i])
                {
                    continue;
                }
                long long v=edge[i].to;
                if(dist[v]>dist[u]+edge[i].w)
                {
                    dist[v]=dist[u]+edge[i].w;
                    if(!vst[v])
                    {
                        q.push(v);
                        vst[v]=true;
                    }
                }
            }
        }
    }
    int main()
    {
        n=read();
        m=read();
        for(long long i=1;i<=m;i++)
        {
            long long x=read(),y=read(),u=read();
            edge[++tot]=(Edge){y,head[x],u,x};
            head[x]=tot;
            edge[++tot]=(Edge){x,head[y],u,y};
            head[y]=tot;
        }
        memset(dist,127,sizeof(dist));
        q.push(1);
        vst[1]=true;
        dist[1]=0;
        SPFA();
        for(long long i=1;i<=n;i++)
        {
            sdis[i]=dist[i];
        }
        len=dist[n];
        memset(dist,127,sizeof(dist));
        q.push(n);
        vst[n]=true;
        dist[n]=0;
        SPFA();
        for(long long i=1;i<=n;i++)
        {
            tdis[i]=dist[i];
        }
        for(long long i=2;i<=tot;i++)
        {
            if(sdis[edge[i].sta]+edge[i].w+tdis[edge[i].to]==len)
            {
                if(!tag[edge[i].sta])
                {
                    que[++top]=edge[i].sta;
                }
                if(!tag[edge[i].to])
                {
                    que[++top]=edge[i].to;
                }
                tag[edge[i].sta]=tag[edge[i].to]=ban[i]=ban[i^1]=true;
            }
        }
        for(long long i=0;i<=17;i++)
        {
            a=b=0;
            for(long long j=1;j<=top;j++)
            {
                if(que[j]&(1<<i))
                {
                    A[++a]=que[j];
                }
                else
                {
                    B[++b]=que[j];
                }
            }
            memset(dist,127,sizeof(dist));
            for(long long j=1;j<=a;j++)
            {
                dist[A[j]]=sdis[A[j]];
                q.push(A[j]);
                vst[A[j]]=true;
            }
            SPFA();
            for(long long j=1;j<=b;j++)
            {
                ans=min(ans,dist[B[j]]+tdis[B[j]]);
            }
            swap(a,b);
            swap(A,B);
            memset(dist,127,sizeof(dist));
            for(long long j=1;j<=a;j++)
            {
                dist[A[j]]=sdis[A[j]];
                q.push(A[j]);
                vst[A[j]]=true;
            }
            SPFA();
            for(long long j=1;j<=b;j++)
            {
                ans=min(ans,dist[B[j]]+tdis[B[j]]);
            }
            if(clock()>1.5*CLOCKS_PER_SEC)
            {
                break;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    escape
  • 相关阅读:
    线程
    实数四则运算表达式的计算,C++ 实现
    [Compiling Principles] LEX基本功能的实现
    2010年ImagineCup,我们共同走过
    [WPF] Felix 的线程学习笔记(一)——从Win32的消息循环说起
    [WPF] Felix 的线程学习笔记(二)——从WPF入手,实现简单的多线程
    [ASP] asp 中的ajax使用
    银行家算法C++实现
    [ASP.NET] 事件与委托的处理
    小郁闷
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13928561.html
Copyright © 2020-2023  润新知