[Codeforces 1105E] Helping Hiasat | State compression, maximum independent set, half

Main idea:

You have registered a new account on a social networking site. This account has n (n ≤ 1 0 5 n(n\leq 10^5n(n105
) Records. Either you changed theID IDonceI D , or anID IDID s ( ∣ s ∣ ≤ 40 ) s(|s|\leq 40) s(s4 0 ) friends visited your space.

You have m (m ≤ 40) m(m\leq 40)m(m4 0 ) friends. Every friend will visit your space at least once. If this friend visits your space every time, yourID IDThe I D and itsID IDThe I D , like, he would happy. I beg you to make many people happy at most.

Question idea:

First consider the final state of the selection,
then it must be any two adjacent 1 1All visitor records between 1 are mutually exclusive.

In other words, there can only be one happy visitor in these visitor records

So the last selected visitor set can be explained as follows: it is impossible for two or more 相邻1操作间visitors to exist in this set

Consider converting to graph theory to build edges on mutually exclusive relationships, so this is obviously the largest independent set. Consider a bipartite graph? Of course not, because there is no guarantee that this is a bipartite graph.

See mmm rangem ≤ 40 m \le40m4 0 , so you can consider folding in halfmmm

Perform state pressure dp, divide the set into two halves, consider the independent set situation of the first half set, the independent set situation of the second half set, and finally consider the independent set situation when the two sets are merged. Assume sss andttt merge, then there must besss mutually exclusive point set inttt does not exist, so it can be compared with the first half ofssThe second half of the combination of s sets must satisfyMAXS ⊕ b [s] MAXS⊕b[s]M A X Sb [ s ] subset. So only need to pressdp dpd p preprocessssThe maximum value of all subsets of s is just fine

For (m / 2) * 2 m / 2 (m / 2) * 2 ^ {m / 2}(m/2)2m / 2 to deal with mutually exclusive point sets and state pressure dp

So the total complexity: O ((m / 2) ∗ 2 m / 2) O((m/2)*2^(m/2))O ( ( m / 2 )2m/2)

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 = 2e6+700;
const ll mod= 1e9+7;
const ll up = 1e13;
const double eps = 1e-9;
const double PI = acos(-1);
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;
vector<int>v;
map<string,int>mp;
int t[55][55];
int vis[55];
int b[maxn],dp[maxn];
int isd[maxn],c[maxn],s[maxn];
int S[maxn],T[maxn];
int work(){
    
    
	int ans = 0;
	int half = m/2;
	int MAX  = 1<<half;
	for(int i=1;i<=half;i++){
    
    
		for(int k=half+1;k<=m;k++){
    
    
			if(t[i][k]) b[i] |= 1<<(k-half-1);
		}
	}
	for(int i=1;i<=half;i++)
		for(int k=1;k<=half;k++)
			if(t[i][k]) S[i] |= 1<<(k-1);
	for(int i=half+1;i<=m;i++)
		for(int k=half+1;k<=m;k++)
			if(t[i][k]) T[i] |= 1<<(k-half-1);

	for(int i=0;i<MAX;i++){
    
    
		int flag = 1;
		for(int k=1;k<=half;k++){
    
    
			if(i>>(k-1)&1){
    
    
				c[i]++;
				s[i] |= b[k];
			}
			if((i>>(k-1)&1)&&(S[k]&i)) flag = 0;
		}
		isd[i] = flag;
		if(isd[i]) ans = max(ans,c[i]);
	}


	ll thalf = m - half;
	MAX = 1<<thalf;
	for(int i=0;i<MAX;i++){
    
    
		int flag = 1,cot = 0;
		for(int k=half+1;k<=m;k++){
    
    
			if(i>>(k-half-1)&1) cot++;
			if((i>>(k-half-1)&1) && (T[k]&i)) flag = 0;
		}
		if(flag) dp[i] = cot,ans = max(ans,cot);
	}

	for(int i=0;i<MAX;i++){
    
    
		for(int k=1;k<=thalf;k++)
			if(i>>(k-1)&1) dp[i] = max(dp[i],dp[i^(1<<(k-1))]);
	}

	MAX = 1<<half;
	int MAXS = (1<<thalf)-1;
	for(int i=0;i<MAX;i++){
    
    
		if(isd[i]) ans = max(ans,c[i]+dp[MAXS^s[i]]);
	}
	return ans;
}
int main(){
    
    
	read(n);read(m);
	int cnt = 0;
	for(int i=1;i<=n;i++){
    
    
		int op;read(op);
		if(op == 1)
			for(int k=1;k<=m;k++) vis[k] = 0;
		else{
    
    
			string s;cin>>s;
			if(!mp[s]) mp[s] = ++cnt;
			int aim = mp[s];
			for(int k=1;k<=m;k++)
				if(vis[k] && k!=aim) t[aim][k] = t[k][aim] = 1;
			vis[aim] = 1;
		}
	}
	di(work());
	return 0;
}
/***
6 3
1
2 aa
2 bb
1
2 aa
2 cc
***/

Guess you like

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