题目链接:https://codeforces.com/contest/1105/problem/E
题意:有 n 个事件,op = 1 表示我可以修改昵称,op = 2 表示一个名为 s_i 的朋友查询我当前的名字。一个朋友是高兴的当且仅当他每次查询我的名字都为 s_i,保证每个朋友至少查询一次我的名字,问最多可以有多少个朋友高兴。
题解:在我两次修改昵称之间,若出现不同的朋友,则他们是互斥的,可以在他们之间连一条边,然后求图的最大独立集,而原图的最大独立集等于补图的最大团,所以求补图的最大团即可。(模板)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 #define lowbit(x) ((x)&(-x)) 11 const int INF = 0x3f3f3f3f; 12 const double eps = 1e-6; 13 const int maxn = 1e5 + 10; 14 const int maxm = 1e6 + 10; 15 const ll mod = 1e9 + 7; 16 17 int n,m,tot = 0; 18 map<string,int>ma,have; 19 int op[maxn],a[50][50]; 20 string s[maxn]; 21 int ans,cnt[50],group[50],vis[50]; 22 23 bool dfs(int u,int pos) { 24 for(int i = u + 1; i <= n; i++) { 25 if(cnt[i] + pos <= ans) return false; 26 if(a[u][i]) { 27 int j; 28 for(j = 0; j < pos; j++) 29 if(!a[i][vis[j]]) break; 30 if(j == pos) { 31 vis[pos] = i; 32 if(dfs(i,pos + 1)) return true; 33 } 34 35 } 36 } 37 if(pos > ans) { 38 for(int i = 0; i < pos; i++) group[i] = vis[i]; 39 ans = pos; 40 return true; 41 } 42 return false; 43 } 44 45 void maxclique() { //最大团 46 ans = -1; 47 for(int i = n; i > 0; i--) { 48 vis[0] = i; 49 dfs(i,1); 50 cnt[i] = ans; 51 } 52 } 53 54 55 int main() { 56 #ifdef local 57 freopen("data.txt", "r", stdin); 58 // freopen("data.txt", "w", stdout); 59 #endif 60 scanf("%d%d",&m,&n); 61 for(int i = 1; i <= m; i++) { 62 scanf("%d",&op[i]); 63 if(op[i] == 2) { 64 cin >> s[i]; 65 if(ma.find(s[i]) == ma.end()) ma[s[i]] = ++tot; 66 } 67 } 68 vector<int>vec; 69 for(int i = 1; i <= m; i++) { 70 if(op[i] == 1) { 71 have.clear(); 72 for(int i = 0; i < vec.size(); i++) { 73 for(int j = i + 1; j < vec.size(); j++) { 74 a[vec[i]][vec[j]] = a[vec[j]][vec[i]] = 1; 75 } 76 } 77 vec.clear(); 78 } else if(have.find(s[i]) == have.end()) vec.pb(ma[s[i]]); 79 } 80 for(int i = 0; i < vec.size(); i++) { 81 for(int j = i + 1; j < vec.size(); j++) { 82 a[vec[i]][vec[j]] = a[vec[j]][vec[i]] = 1; 83 } 84 } 85 for(int i = 1; i <= n; i++) 86 for(int j = 1; j <= n; j++) a[i][j] ^= 1; 87 maxclique(); 88 if(ans < 0) ans = 0; 89 printf("%d\n",ans); 90 return 0; 91 }
Codeforces Round #533 (Div. 2) E. Helping Hiasat(最大独立集)
原文:https://www.cnblogs.com/scaulok/p/10296835.html