• AtCoder Beginner Contest 190 E


    题意

    (N) 个数,其中 (M) 对数可以相邻,求出包含所给序列 (C) 的最短序列的长度。(1leq Nleq 10^5,1leq Mleq10^5,1leq K leq17)
    题目链接:https://atcoder.jp/contests/abc190/tasks/abc190_e

    分析

    可以发现 (K) 很小,应该如何利用?令 (dp[i][j]) 表示包含 (i) 方案,且最近一个位置是第 (j) 个位置的最少花费,其中 (i) 为状态,为 (1) 的二进制位表示该位置的数字已经包含。那么 (dp[nextstate][j]=min(dp[nextstate][j],dp[i][j]+dis[j][x])),其中 (nextstate=i+(1<<x))(dis[j][x]) 可通过 (bfs) 求出。

    代码

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int N=1e5+5;
    const int maxn=2e5+5;
    int dis[20][N],n,dp[maxn][20],k,c[20];
    vector<int>pic[N];
    bool vis[N];
    void bfs(int s)
    {
        queue<int>que;
        for(int i=1;i<=n;i++) vis[i]=0;
        que.push(c[s]);
        dis[s][c[s]]=0;
        vis[c[s]]=1;
        while(!que.empty())
        {
            int now=que.front();
            que.pop();
            for(auto v:pic[now])
            {
                if(vis[v]) continue;
                dis[s][v]=dis[s][now]+1;
                vis[v]=1;
                que.push(v);
            }
        }
    }
    int main()
    {
        int m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            pic[a].pb(b);
            pic[b].pb(a);
        }
        scanf("%d",&k);
        for(int i=0;i<k;i++)
            scanf("%d",&c[i]);
        for(int i=0;i<k;i++)
            for(int j=1;j<=n;j++)
                dis[i][j]=inf;
        for(int i=0;i<k;i++)
            bfs(i);
        for(int i=0;i<(1<<k);i++)
            for(int j=0;j<k;j++)
                dp[i][j]=inf;
        for(int i=0;i<k;i++) dp[(1<<i)][i]=1;
        for(int i=0;i<(1<<k);i++)
        {
            for(int j=0;j<k;j++)
            {
                if(dp[i][j]==inf) continue;
                for(int x=0;x<k;x++)
                {
                    if(x==j||dis[j][c[x]]==inf) continue;
                    if((i>>x)&1) continue;
                    int nextstate=i+(1<<x);
                    dp[nextstate][x]=min(dp[i][j]+dis[j][c[x]],dp[nextstate][x]);
                }
            }
        }
        int ans=inf;
        for(int i=0;i<k;i++) ans=min(dp[(1<<k)-1][i],ans);
        if(ans>=inf) printf("-1
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    Node-MySQL 官方文档
    ES6对象的扩展
    async 函数的含义和用法
    express如何使用session与cookie
    uni-app 事件
    uni-app 生命周期
    uni-app 底部导航栏
    用于多扩展目标跟踪的线性时间联合概率数据关联
    基于随机超曲面模型的扩展目标跟踪
    18用于大型程序的工具之多重继承与虚继承
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/14352096.html
Copyright © 2020-2023  润新知