2017 CCPC秦皇岛 D

来源:互联网 发布:chip数据 编辑:程序博客网 时间:2024/04/28 20:37

考虑到对于一个联通块,最后一个加的点一定是度数最大的点,并且度数是联通块的siz-1。而把这个点删掉之后的图,因为每个点的度数同减一,依然满足上述性质。于是反过来想可以发现,若有解,则将最终度数从小到大依次加入图的方案一定是一组解。判断这种加点方式是否成立即可。用并查集维护联通性。

#include <bits/stdc++.h>using namespace std;const int maxn=105000;vector<int>g[maxn], ans[maxn];int n, m;int fa[maxn], siz[maxn], id[maxn], degree[maxn];bool vis[maxn];bool cmp(int x, int y){    return degree[x]<degree[y];}int f(int x){    if(x==fa[x])return x;    return fa[x]=f(fa[x]);}int main(){    int T;    scanf("%d", &T);    while(T--){        scanf("%d%d", &n, &m);        for(int i=1;i<=n;i++){            g[i].clear();            ans[i].clear();            fa[i]=id[i]=i, siz[i]=1;            degree[i]=0;            vis[i]=false;        }        for(int i=1;i<=m;i++){            int u, v;            scanf("%d%d", &u, &v);            degree[u]++, degree[v]++;            g[u].push_back(v);            g[v].push_back(u);        }        sort(id+1, id+1+n, cmp);        //for(int i=1;i<=n;i++)printf("%d%c", id[i], i==n?'\n':' ');        bool ok=true;        for(int i=1;i<=n;i++){            int u=id[i];            int sum=0;            vis[u]=true;            for(int j=0;j<g[u].size();j++){                int v=g[u][j];                if(!vis[v])continue;                sum++;                v=f(v);                if(v==u)continue;                ans[i].push_back(v);                fa[v]=u;                siz[u]+=siz[v];            }            if(siz[u]!=sum+1){                ok=false;                break;            }        }        if(!ok)printf("No\n");        else {            printf("Yes\n");            for(int i=1;i<=n;i++){                printf("%d %d", id[i], (int)ans[i].size());                for(int j=0;j<ans[i].size();j++){                    printf(" %d", ans[i][j]);                }                printf("\n");            }        }    }}