Living-Dream 系列笔记 第91期
最大团
一张图的最大团被定义为它的一个极大的完全子图。
对于任意一张图,我们都有如下结论:其最大团就是其补图的最大独立集。读者自证不难。
于是乎,只要一张图的补图为二分图,我们就可以轻松求出它的最大团。
P2764
抽象一下题意,我们发现我们需要连一条边使得最大团的大小加一。
在补图中,连边会变为删边,又因为 \(最大团 = 补图最大独立集 = 补图总点数-最小点覆盖=补图总点数-最大匹配\),所以要让最大团更大,最大匹配应当更小。
于是,我们暴力地枚举删哪一条匹配,然后暴力地检验最大匹配是否变少即可。
时间复杂度最坏可以达到 \(O(n^5)\),显然无法通过,但可以获得 \(60 pts\) 的高分。正解也许会出现在第 93 期中。
code
#include<bits/stdc++.h> using namespace std; const int N=1e4+5; int n,m; int idx,ans; int match[N],match2[N],vis[N],color[N]; vector<int> G[N],T[N]; vector<pair<int,int> > Ans; void fillit(int cur,int c){ color[cur]=c; for(int i:G[cur]) if(!color[i]) fillit(i,3-c); } bool hungary(int* mm,int cur,int pre,int nxt){ if(vis[cur]==idx){ return 0; } vis[cur]=idx; for(int i:T[cur]){ if(cur==pre&&i==nxt) continue; if(!mm[i]||hungary(mm,mm[i],pre,nxt)){ mm[i]=cur; return 1; } } return 0; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>n>>m; for(int i=1,u,v;i<=m;i++){ cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++) if(!color[i]) fillit(i,1); for(int i=1;i<=n;i++){ for(int j:G[i]){ if(color[i]==1) T[i].push_back(j); else T[j].push_back(i); } } for(int i=1;i<=n;i++){ if(color[i]==1){ idx++; if(hungary(match,i,-1,-1)) ans++; } } for(int i=1;i<=n;i++){ if(color[i]==2){ memset(match2,0,sizeof match2); int nowans=0; for(int j=1;j<=n;j++){ if(color[j]==1){ idx++; if(hungary(match2,j,match[i],i)) nowans++; } } if(nowans<ans) Ans.push_back({min(match[i],i),max(match[i],i)}); } } sort(Ans.begin(),Ans.end()); cout<<Ans.size()<<'\n'; for(auto i:Ans) cout<<i.first<<' '<<i.second<<'\n'; return 0; }
总结:
-
寻找一个网络中两两之间有关系的一群东西,考虑最大团。
-
最大团问题分析补图。
-
做题从概念出发。
P2423
根据朋友圈的定义我们容易发现这是一个最大团问题,但是哪来的二分图???
进行一个条件的解读:
-
A 国:对于两个友善值为 \(a,b\) 的 A 国人,\((a\mathbin{\mathrm{xor}} b) \bmod 2=1\) 这个条件意味着若它们是朋友,则 \(a,b\) 奇偶性不同。
-
B 国:反之。第二个条件无需解读,直接判即可。
那么 B 国的补图就是 \(a,b\) 奇偶性不同的连边,我们把奇数点看作左部点,偶数点看作右部点,二分图出来了。
显然不考虑 A 国的时候,本题答案即为 \(B\) 国的最大团。
但是 A 国加进来怎么办?这启发我们去挖掘性质。
因为 A 国是奇偶不同连边,根据抽屉原理,A 国一定不能加进来超过 \(2\) 人,因为到了第 \(3\) 个人就一定会与前两个人中的某一个不连边,形成不了最大团。
那么我们暴力地去枚举 A 国加哪些人(如果加两个人,则他们俩必须是朋友),然后将他们所连接的 B 国人求一次最大团即可。
但是有一种方法是不行的,就是把 B 国的人全放进来求一遍最大团,然后再选 A 国人加入。一方面我们无法知道最大团的方案,也就无法验证其正确性;另一方面,将 B 国人全求一遍最大团不一定最优,我们完全可以少选几个然后多加几个 A 国人进来。
同样,将 A 国人加入和 B 国人一起求最大团更是不行的,因为我们无法保证 A 国人加进来以后还是二分图。
为什么我要讲以上两种错误方法呢,还不是因为老师的误导(光速逃)。
综上,本题是巨大困难图论题,并且结合了数学知识,考察了我们解读条件、挖掘性质的能力,还要求我们具有转换角度的思想(因为正常人都会往错误方法一想),确实是一道极好的题目。
code
#include<bits/stdc++.h> using namespace std; const int N=3e3+5; int t,a,b,m; int ans,idx,idxx; int ap[N],bp[N]; int match[N],ok[N],vis[N]; bool yes[N][N]; vector<int> G[N]; bool hungary(int cur){ for(int i:G[cur]){ if(vis[i]!=idx&&ok[i]==idxx){ vis[i]=idx; if(!match[i]||hungary(match[i])){ match[i]=cur; return 1; } } } return 0; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>t; while(t--){ cin>>a>>b>>m; for(int i=1;i<=a;i++) cin>>ap[i]; for(int i=1;i<=b;i++) cin>>bp[i]; memset(yes,0,sizeof yes); for(int i=1,u,v;i<=m;i++) cin>>u>>v,yes[u][v]=1; for(int i=1;i<=b;i++) G[i].clear(); for(int i=1;i<=b;i++) for(int j=1;j<=b;j++) if((bp[i]&1)&&!(bp[j]&1)&&!(__builtin_popcount(bp[i]|bp[j])&1)) G[i].push_back(j); ans=idx=idxx=0; memset(match,0,sizeof match); for(int i=1;i<=b;i++){ if(bp[i]&1){ idx++; if(hungary(i)) ans++; } } ans=b-ans; memset(ok,0,sizeof ok); for(int i=1;i<=a;i++){ idxx++; int all=0; for(int j=1;j<=b;j++) if(yes[i][j]) ok[j]=idxx,all++; memset(match,0,sizeof match); int nowans=0; for(int j=1;j<=b;j++){ if(ok[j]==idxx&&(bp[j]&1)){ idx++; if(hungary(j)) nowans++; } } ans=max(ans,all-nowans+1); } for(int i=1;i<=a;i++){ for(int j=i+1;j<=a;j++){ if((ap[i]^ap[j])&1){ idxx++; int all=0; for(int k=1;k<=b;k++) if(yes[i][k]&&yes[j][k]) ok[k]=idxx,all++; memset(match,0,sizeof match); int nowans=0; for(int k=1;k<=b;k++){ if(ok[k]==idxx&&(bp[k]&1)){ idx++; if(hungary(k)) nowans++; } } ans=max(ans,all-nowans+2); } } } cout<<ans<<'\n'; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】