题解 P7320【可怜的团主】
题目传送门
题目大意:
给定一张简单无向连通图。
问是否能找到
若没有则 Poor lnlhm
通过套取数据 得出并不存在没有的情况(结尾给出证明)
考虑 dfs 树,将整张图 dfs 后,回溯时处理出独立集。
如果可以将
if(!ind[x])
{
ans.push_back(x);
for(int i=fir[x];i;i=nex[i])
ind[poi[i]]=1;
if(ans.size()==n/3) Print_2();
}
再处理后的一颗树上,存下叶子节点,将所有叶子进行匹配,如果不能进行完美的匹配,就可以把根节点1看做叶子节点。
将所有叶子节点按照 dfs 序排序,匹配时可以将
处理后如果不能达到
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define N 1000010
using namespace std;
int re() {
int p=0,f=1; char i=getchar();
while(i<'0'||i>'9') {if(i=='-') f=-1;i=getchar();}
while(i>='0'&&i<='9') p=p*10+i-'0',i=getchar();
return f*p;
}
int n,m,sum,cnt,num,lit;
int fir[N],nex[N],poi[N];
int dfn[N],dep[N],f[N],loc[N];
bool ind[N];
int lef[N];
vector<int> ans;
void ins(int x,int y) {
nex[++sum]=fir[x];
poi[sum]=y;
fir[x]=sum;
}
bool cmp(int x,int y) {
return dfn[x]<dfn[y];
}
int a[N],b[N];
void Jump(int x,int y)
{
lit++;
int step_a=0,step_b=0;
while(x!=y)
{
if(dep[x]>dep[y])
a[++step_a]=x,x=f[x];
else
b[++step_b]=y,y=f[y];
}
a[++step_a]=x;
printf("%d ",step_a+step_b);
for(int i=1;i<=step_a;i++)
printf("%d ",a[i]);
for(int i=step_b;i>=1;i--)
printf("%d ",b[i]);
}
void Print_1() {
printf("1\n");
for(int i=1;i<=num/2;i++)
{
int u=lef[i],v=lef[i+num/2];
Jump(u,v);
puts("");
}
int lim=n/6;
if(n%6) lim++;
for(int i=lit;i<lim;i++)
printf("1 %d\n",i);
}
void Print_2() {
printf("2\n");
for(int i=0;i<ans.size();i++)
printf("%d ",ans[i]);
exit(0);
}
void dfs(int x,int fa)
{
int flag=0;
dfn[x]=++cnt;
dep[x]=dep[fa]+1;
loc[cnt]=x;
f[x]=fa;
for(int i=fir[x];i;i=nex[i]) {
int p=poi[i];
if(dep[p]) continue;
dfs(p,x);
flag++;
}
if(flag==0||(flag==1&&x==1))
lef[++num]=x;
if(!ind[x]) {
ans.push_back(x);
for(int i=fir[x];i;i=nex[i])
ind[poi[i]]=1;
if(ans.size()==n/3) Print_2();
}
}
int main()
{
n=re(); m=re();
for(int i=1;i<=m;i++) {
int u,v;
u=re(); v=re();
ins(u,v);
ins(v,u);
}
dfs(1,0);
sort(lef+1,lef+num+1,cmp);
Print_1();
return 0;
}
- 证明:
如果最大独立集小于
如果
故不存在最大独立集既小于
如有不妥之处,请不要吝啬您的评论~