题目链接: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]; 20 string s[maxn]; 21 22 int mx[50], g[50][50], f[50][50], ans; 23 24 int dfs(int cur, int tot) { 25 if(!cur) { 26 if(tot > ans) 27 return ans = tot, 1; 28 return 0; 29 } 30 for(int i = 0, j, u, nxt; i < cur; i++) { 31 if(cur - i + tot <= ans) 32 return 0; 33 u = f[tot][i], nxt = 0; 34 if(mx[u] + tot <= ans) 35 return 0; 36 for(j = i + 1; j < cur; j++) 37 if(g[u][f[tot][j]]) 38 f[tot + 1][nxt++] = f[tot][j]; 39 if(dfs(nxt, tot + 1)) 40 return 1; 41 } 42 return 0; 43 } 44 45 46 int main() { 47 #ifdef local 48 freopen("data.txt", "r", stdin); 49 // freopen("data.txt", "w", stdout); 50 #endif 51 scanf("%d%d", &m, &n); 52 for(int i = 1; i <= m; i++) { 53 scanf("%d", &op[i]); 54 if(op[i] == 2) { 55 cin >> s[i]; 56 if(ma.find(s[i]) == ma.end()) 57 ma[s[i]] = tot++; 58 } 59 } 60 vector<int>vec; 61 for(int i = 1; i <= m; i++) { 62 if(op[i] == 1) { 63 have.clear(); 64 for(int i = 0; i < vec.size(); i++) { 65 for(int j = i + 1; j < vec.size(); j++) { 66 g[vec[i]][vec[j]] = g[vec[j]][vec[i]] = 1; 67 } 68 } 69 vec.clear(); 70 } else if(have.find(s[i]) == have.end()) 71 vec.pb(ma[s[i]]); 72 } 73 for(int i = 0; i < vec.size(); i++) { 74 for(int j = i + 1; j < vec.size(); j++) { 75 g[vec[i]][vec[j]] = g[vec[j]][vec[i]] = 1; 76 } 77 } 78 for(int i = 0; i < n; i++) 79 for(int j = 0; j < n; j++) 80 g[i][j] ^= 1; 81 82 int j,k; 83 for(int i = n - 1; ~i; dfs(k, 1), mx[i--] = ans) 84 for(k = 0, j = i + 1; j < n; j++) 85 if(g[i][j]) 86 f[1][k++] = j; 87 printf("%d ", ans); 88 return 0; 89 }