FZU 2093 寻找兔子 (状态压缩dp)

题目链接
对于每一个点,至多有一个没有确定的点,可以确定兔子的位置。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define LL __int64
#define cl(a,b) memset(a,b,sizeof(a))
#define pb push_back

const int maxn = 16;
const int inf  = 1<<25;
const __int64 mod = 1000000007;

int edge[maxn*10];//使用二进制存边f[x]|=1<<y;多条边的信息
int dp[1<<maxn];//表示到达状态i的最小步数,i状态的1表示这个点已经确定
/*
*解法的可能,对于某一点,要么相邻的点全部是确定的,要么只有一个没有确定
*/
queue<int>q;

int main(){
    int T;scanf("%d",&T);
    while(T--){
        int n,m;scanf("%d%d",&n,&m);

        cl(edge,0);
        for(int i=0;i<=(1<<n);i++)dp[i]=inf;

        for(int i=0;i<m;i++){
            int x,y;scanf("%d%d",&x,&y);x--;y--;//编号从0开始
            edge[x]|=1<<y;
            edge[y]|=1<<x;
        }
        //找到孤立点,自身连边
        for(int i=0;i<n;i++)if(!edge[i])edge[i]=1<<i;

        q.push(0);dp[0]=0;
        while(!q.empty()){
            int x=q.front();q.pop();
            //找出当前集合x可以到达的所有点的集合cur
            int cur=0;
            for(int i=0;i<n;i++)if((x&edge[i])==edge[i])cur|=1<<i;
            for(int i=0;i<n;i++)for(int j=i+1;j<n;j++)if(dp[cur|(1<<i)|(1<<j)]>dp[x]+1){
                dp[cur|(1<<i)|(1<<j)]=dp[x]+1;
                q.push(cur|(1<<i)|(1<<j));
            }
        }
        int all = (1<<n)-1;
        int ans = dp[all];//第一种情况,这个点相邻的点全部确定了

        for(int i=0;i<n;i++)ans=min(ans,dp[all^(1<<i)]);//第二种可能,这个点,相邻的点只有一个没有确定
        printf("%d\n",ans==inf?-1:ans);
        while(!q.empty())q.pop();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值