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 \le18N≤1 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[i⊕s]+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=(i−1)&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(i−1 ) & 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^k∑k=1k=NCNk∗2k = ∑ 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=NCNk∗2k∗1N - 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
***/