bzoj 4296 [PA2015]Mistrzostwa宽搜 并查集

    xiaoxiao2021-12-01  66

    先将所有度数小于d的点推入队列,然后把这些点相连的点度数-1,如果一个没入队过的点度数-1后度数小于d,那么把这个点入队。 然后找没入队过的点形成的最大连通块就是答案。

    #include <bits/stdc++.h> using namespace std; #define N 210000 int n,m,d,tot,pos; int head[N],nex[N<<1],to[N<<1]; int vis[N],fa[N],size[N],du[N]; queue<int>que; void add(int x,int y) { tot++; nex[tot]=head[x];head[x]=tot; to[tot]=y; } int find(int x){return x==fa[x] ? x:fa[x]=find(fa[x]);} int main() { //freopen("tt.in","r",stdin); scanf("%d%d%d",&n,&m,&d); for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y);add(y,x); du[x]++;du[y]++; } for(int i=1;i<=n;i++) if(du[i]<d)que.push(i),vis[i]=1; while(!que.empty()) { int t=que.front();que.pop(); for(int i=head[t];i;i=nex[i]) if(!vis[to[i]]&&--du[to[i]]<d) vis[to[i]]=1,que.push(to[i]); } for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=n;i++) if(!vis[i]) for(int j=head[i];j;j=nex[j]) if(!vis[to[j]]) { if(find(i)!=find(to[j])) fa[find(i)]=find(to[j]); } for(int i=1;i<=n;i++) if(!vis[i])size[find(i)]++; for(int i=1;i<=n;i++) if(!vis[i]&&size[find(i)]>size[pos]) pos=find(i); if(!pos)return puts("NIE"),0; printf("%d\n",size[pos]); for(int i=1;i<=n;i++) if(find(i)==pos) printf("%d ",i); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-679552.html

    最新回复(0)