E - Magical Ornament 题解(图论+状压dp)

题目链接

题目大意

给你n个宝石,有m对(a[i],b[i])关系,以及k种必须出现的宝石

你要保证出现k种必须出现的宝石(每种宝石>=1即可),且出现的宝石要满足m对关系的两两相邻

求最少的宝石数,不满足则直接输出-1

\(1<=n<=1e5\;\;0<=m<=1e5\;\;1<=k<=17\)

题目思路

首先相邻则可以当作建边

然后用bfs预处理这k的点的两两直接的距离

然后用状压dp转移

\(dp[sta][last]\) 表示当前状态为sta,且现在在last点

用状压最朴素的转移即可

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=3e5+5,inf=0x3f3f3f3f,mod=998244353;
const int eps=1e-6;
int n,m,k;
int head[maxn],cnt;
int c[maxn];
int dis[20][20],len[maxn];
int dp[1<<17][20];
struct edge{
    int to,next;
}e[maxn<<1];
void add(int u,int v){
    e[++cnt]={v,head[u]};
    head[u]=cnt;
}
void bfs(int x){
    memset(len,0x3f,sizeof(len));
    len[x]=0;
    queue<int> que;
    que.push(x);
    while(!que.empty()){
        int x=que.front();
        que.pop();
        for(int i=head[x];i;i=e[i].next){
            if(len[e[i].to]!=inf) continue;
            len[e[i].to]=len[x]+1;
            que.push(e[i].to);
        }
    }
}
signed main(){
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<=m;i++){
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&c[i]);
    }
    for(int i=1;i<=k;i++){
        bfs(c[i]);
        for(int j=1;j<=k;j++){
            dis[i][j]=len[c[j]];
        }
    }
    memset(dp,0x3f,sizeof(dp));
    for(int i=1;i<=k;i++){ //预处理
        dp[1<<(i-1)][i]=1;
    }
    for(int sta=0;sta<(1<<k);sta++){
        for(int last=1;last<=k;last++){
            if(!(sta&(1<<(last-1)))||dp[sta][last]==inf) continue; //没有交集
            for(int nxt=1;nxt<=k;nxt++){
                if(sta&(1<<(nxt-1))) continue; //已经有交集了
                dp[sta|(1<<(nxt-1))][nxt]=min(dp[sta|(1<<(nxt-1))][nxt],dp[sta][last]+dis[last][nxt]);
            }
        }
    }
    int ans=inf;
    for(int i=1;i<=k;i++){
        ans=min(ans,dp[(1<<k)-1][i]);
    }
    if(ans==inf) ans=-1;
    printf("%d\n",ans);
    return 0;
}

上一篇:2021.1.30 刷题(滑动窗口最大值-单调队列)


下一篇:[CF936B] Sleepy Game - DFS,BFS