AtCoder Beginner Contest 187F Close Group | State pressure dp, subset enumeration

emmm, a better idea, forgot to summarize and make up.

Topic

Give an NNUndirected graph of N points, withmmWith m edges, the query is divided into at least several connected blocks so that each connected block is a complete graph?

Topic idea

Since N ≤ 18 N \le18N1 8 , so consider the pressure dp

Obviously, dp [i] dp[i]d p [ i ] represents the smallest number of states that state i can be divided into, then consideriiall substates of i sss and consider the statessIs s legal? If it is legal, then there must be:dp [i] = dp [i ⊕ s] + 1 dp[i] = dp[i⊕s]+1dp[i]=dp[is]+1

So considering these states, enumerate the states from small to large, and put all the substates ss of the current state that can form a complete graph.s , try to add this status to see if you can update the answer

Enumeration subset:

s s s is the current state, sossmust bes的所有子集为:
f o r ( i n t   i = s ; i ; i = ( i − 1 ) & s ) for(int\ i=s;i;i = (i-1)\&s) f o r ( i n t i =s;i;i=(i1)&s)

Here is a simple proof that the general enumeration subset is to let the current state sss minus1 11 , each time it is judged whether it is a subset of the current state,(i − 1) & s (i-1)\&s(i1 ) & s can save a lot of useless states, so that it can be changed to the current maximum andsss has an intersection state

Prove the complexity of this writing:

For NNA subset of the set of N elements, containingkkThe number of sets of k elements isCN k C_N^kCNkA

For the quantity kkThe set of k , all the subsets are:2 k 2^k2k th

So all the complexity is: ∑ k = 1 k = NCN k ∗ 2 k \sum_{k=1}^{k=N}C_N^k*2^kk=1k=NCNk2k = ∑ k = 1 k = N C N k ∗ 2 k ∗ 1 N − k \sum_{k=1}^{k=N}C_N^k*2^k*1^{N-k} k=1k=NCNk2k1N - k =3 N 3 ^ N3N

After understanding the complexity, just write it, and I will add a similar one later

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn =5e5+700;
const ll mod= 1e9+7;
const ll up = 1e13;
const double eps = 1e-9;
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int mp[25][25];
int b[25],dp[maxn],s[maxn];
int main(){
    
    
	read(n);read(m);
	for(int i=1;i<=m;i++){
    
    
		int x,y;read(x);read(y);
		mp[x][y] = mp[y][x] = 1;
	}
	int MAX = 1<<n;
	for(int i=1;i<=n;i++) b[i] = 1<<(i-1);
	for(int i=1;i<=n;i++)
		for(int k=1;k<=n;k++)
			if(mp[i][k]) b[i] |= 1<<(k-1);

	for(int i=1;i<MAX;i++){
    
    
		int flag = 0;
		for(int k=1;k<=n;k++){
    
    
			if(i>>(k-1)&1){
    
    
				if(!((b[k]|i)==b[k])){
    
    
					flag = 1;
					break;
				}
			} 
		}
		if(!flag) s[i] = 1;
	}

	for(int i=1;i<MAX;i++) dp[i] = 1e9+7;
	dp[0] = 0;
	for(int i=1;i<MAX;i++){
    
    
		for(int k=i;k;k=(k-1)&i){
    
    ///所有子集
			if(s[k]) dp[i] = min(dp[i],dp[i^k]+1);
		}
	}
	printf("%d\n",dp[MAX-1]);
	return 0;
}
/***
2 3
2 3 2
4 5 4 1 5
***/

Guess you like

Origin blog.csdn.net/qq_43857314/article/details/112383286