Title:
The meaning of the problem is transformed into a graph theory problem: given a undirected graph with m points, the maximum independent set is obtained. (m≤40)(m \leq 40)(m≤40)
Links:
https://codeforces.com/contest/1105/problem/E
Solutions:
It is obvious that the direct state pressure judgment is not feasible. Considering the half optimization, the two halves of the state pressure are obtained separately, and the maximum independent set of the right part state satisfied by each left part state query is obtained.
Reference code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; #define sz(a) ((int)a.size()) #define pb push_back #define lson (rt << 1) #define rson (rt << 1 | 1) #define gmid (l + r >> 1) const int maxn = 1e5 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; struct Qr{ int opt; string s; } qr[maxn]; int G[55][55]; map<string, int> mp, id; int ltl[55], ltr[55], rtr[55]; int dp1[1 << 20], dp2[1 << 20]; int n, m, tot; int main(){ ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m; for(int i = 1; i <= n; ++i){ cin >> qr[i].opt; if(qr[i].opt == 2) cin >> qr[i].s, mp[qr[i].s] = 1; } int p = 1; while(p <= n && qr[p].opt == 2){ mp[qr[p].s] = 0; ++p; } for(auto it : mp){ if(it.second) id[it.first] = tot++; } int nl = (tot + 1) >> 1, nr = tot - nl; while(p <= n){ while(p <= n && qr[p].opt == 1) ++p; set<int> st; while(p <= n && qr[p].opt == 2){ st.insert(id[qr[p].s]); ++p; } for(auto it1 : st){ for(auto it2 : st){ if(it1 >= it2) continue; if(it1 < nl && it2 < nl) ltl[it1] |= 1 << it2, ltl[it2] |= 1 << it1; else if(it1 < nl && it2 >= nl) ltr[it1] |= 1 << (it2 - nl); else rtr[it1 - nl] |= 1 << (it2 - nl), rtr[it2] |= 1 << (it1 - nl); } } } int ret = 0, lim1 = 1 << nl, lim2 = 1 << nr; for(int i = 0; i < lim2; ++i){ int cnt = 0; for(int j = 0; j < nr; ++j){ if((i >> j) & 1){ ++cnt; if(rtr[j] & i) { cnt = -inf; break; } } } dp2[i] = cnt; } // cout << nl << " x " << nr << endl; // for(int i = 0; i < lim2; ++i){ // cout << dp2[i] << " yy " << i << endl; // } for(int i = 0; i < lim2; ++i){ for(int j = 0; j < nr; ++j){ if((i >> j) & 1){ dp2[i] = max(dp2[i], dp2[i ^ (1 << j)]); } } } // for(int j = 0; j < nr; ++j){ // for(int i = 0; i < lim2; ++i){ // if((i >> j) & 1){ // dp2[i] = max(dp2[i], dp2[i ^ (1 << j)]); // } // } // } for(int i = 0; i < lim1; ++i){ int cnt = 0; for(int j = 0; j < nl; ++j){ if((i >> j) & 1){ ++cnt; if(ltl[j] & i) { cnt = -inf; break; } } } dp1[i] = cnt; } int msk = lim2 - 1; for(int i = 0; i < lim1; ++i){ int sta = 0; for(int j = 0; j < nl; ++j){ if((i >> j) & 1){ sta |= ltr[j]; } } sta ^= msk; ret = max(ret, dp1[i] + dp2[sta]); } cout << ret << endl; return 0; }