标签:void 朋友 scanf iterator 之间 check false for bsp
神仙题,感觉不止2200的难度
先要建图
可以发现无论有多少个连续的1操作,都是可以看做1次1操作
那么可以将以这1作为分组的界限,将连续的2操作分为一组
然后将每一个朋友姓名的字符串用map哈希成数字
此时将每一个朋友在哪一组出现过都处理出来
称两个朋友是冲突的,当且仅当这两个朋友同时出现在任意一组中
那么将这两个朋友之间连边,那么图就建出来了
比赛时我就想到这里,然后用拓扑序乱搞,竟然水过了前29个点
后来jzy大佬,喊了一声最大独立集,我就恍然大悟
然后答案就是这张图的最大独立集
最大独立集就是原图补图的最大团
因为m是40的范围,直接暴力会超时,所以要有dp优化
MYY大佬是折半搜索的(好吧我不想写)
当然,如果会高级算法也能直接过(然而我不会)
#include <bits/stdc++.h> #pragma GCC optimize(2) #define ll long long using namespace std; const int MAXN=100000+10; int n,m,w,si[51],vi[51],ans,g; int MIN,fx[51][51],dp[51],s[51]; map <string,int> mp; struct node { int op; string name; }sh[MAXN]; vector <int> f[MAXN],ti[51],e[51]; set <pair<int,int> > q; bool check(int x,int y) { for (int i=0;i<(int)ti[x].size();i++) { vector <int> :: iterator it; it=lower_bound(ti[y].begin(),ti[y].end(),ti[x][i]); if (it==ti[y].end()) continue; if (*it==ti[x][i]) return true; } return false; } bool judge(int x,int end) { for (int i=1;i<end;i++) { if (!fx[s[i]][x]) return false; } return true; } void dfs(int x,int wh)//暴力求出补图的最大团 { if (x+m-wh+1<=ans || x+dp[wh]<=ans) return; for (int i=wh;i<=m;i++) { if (judge(i,x+1)) { s[x+1]=i; dfs(x+1,i+1); } } if (x>ans) ans=x; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&sh[i].op); if (sh[i].op==2) { cin>>sh[i].name; if (mp[sh[i].name]==0) { w++; mp[sh[i].name]=w;//离散化 } } } int bl=-1; w=0; for (int i=1;i<=n;i++)//分组 { if (bl==-1 && sh[i].op==2) { w++; bl=0; f[w].push_back(mp[sh[i].name]); } else if (bl==0 && sh[i].op==2) { f[w].push_back(mp[sh[i].name]); } else if (bl==0 && sh[i].op==1) bl=-1; } for (int i=1;i<=w;i++) { for (int j=0;j<(int)f[i].size();j++) ti[f[i][j]].push_back(i); } for (int i=1;i<=m;i++) { for (int j=i+1;j<=m;j++) { if (check(i,j)) { e[i].push_back(j); e[j].push_back(i); } } } for (int i=1;i<=m;i++) { for (int j=1;j<=m;j++) fx[i][j]=1; } for (int i=1;i<=m;i++) { for (int j=0;j<(int)e[i].size();j++) fx[i][e[i][j]]=0;//建出原图的补图 fx[i][i]=0; } dp[m]=1; ans=0; for (int i=m-1;i>=1;i--)//求出补图的最大团 { s[1]=i; dfs(1,i+1); dp[i]=ans; } printf("%d\n",dp[1]); }
标签:void 朋友 scanf iterator 之间 check false for bsp
原文地址:https://www.cnblogs.com/huangchenyan/p/11258414.html