zoukankan      html  css  js  c++  java
  • CF566E Restoring Map

    题意:乱序给你树上的每一个节点与之相距<=2的节点集合(并不知道这具体是哪个节点)。

    还原整棵树。

    标程:

     1 #include<bits/stdc++.h>
     2 #define P pair<int,int>
     3 #define fir first
     4 #define sec second
     5 using namespace std;
     6 const int N=1005;
     7 vector<P> vec[N];
     8 bitset<N> bit[N];
     9 int n,f[2*N],x,u,v,k;
    10 int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    11 void merge(int x,int y){f[find(x)]=find(y);}
    12 int main()
    13 {
    14     scanf("%d",&n);
    15     for (int i=1;i<=n;i++)
    16     {
    17         scanf("%d",&k);
    18         while (k--) scanf("%d",&x),bit[x][i]=1;
    19     }
    20     if (n==2) return puts("1 2"),0;
    21     for (int i=1;i<=2*n;i++) f[i]=i;
    22     for (int i=1;i<=n;i++)
    23       for (int j=i+1;j<=n;j++)
    24       {
    25           int cnt=(int)(bit[i]&bit[j]).count();
    26           if (cnt==1) merge(i,j),merge(i+n,j+n);
    27           else if (cnt==2) merge(i+n,j),merge(i,j+n);
    28           else vec[cnt].push_back(P(i,j));
    29       }
    30     if (vec[n].size()==n*(n-1)/2)//特判星 
    31     {
    32         for (int i=2;i<=n;i++) printf("1 %d
    ",i);
    33         return 0; 
    34     }
    35     if (vec[n].size()==1)//特判流星锤 
    36     {
    37         printf("%d %d
    ",u=vec[n][0].fir,v=vec[n][0].sec);
    38         for (int i=1;i<=n;i++)
    39           if (i!=u&&i!=v) {merge(i,u),merge(i+n,u+n),merge(i+n,v),merge(i,v+n);break;}
    40         for (int i=1;i<=n;i++)
    41           if (i!=u&&i!=v)
    42             if (find(i)==find(u)) printf("%d %d
    ",i,u);else printf("%d %d
    ",i,v);
    43         return 0;
    44     }
    45     for (int i=n;i>=3;i--)
    46       for (int j=0;j<vec[i].size();j++)
    47         if (u=vec[i][j].fir,v=vec[i][j].sec,find(u)!=find(v))
    48         {
    49               printf("%d %d
    ",u,v);
    50               merge(u+n,v);merge(u,v+n);
    51         } 
    52     return 0;
    53 } 
    View Code

    注意有很多特判:n=2,星星图,流星锤图(后两个由于不满足贪心)。

    题解:贪心+染色

    考虑对相邻节点集合取交,设大小为cnt。若cnt=1,这两个点必同色;cnt=2,必异色。剩下的存入一个vector。然后按cnt从大到小枚举两点,如果他们不在同色区间中,相信它们之间有边。并更新并查集。

  • 相关阅读:
    RocketMQ(十):数据存储模型的设计与实现
    常用sql语句
    配色方案
    WPF界面MahApps.Metro之应用
    使用 Zendesk maxwell 对接 kinesis (include producer and consumer)
    oracle报错【ORA-01017:用户名/口令无效;登录被拒绝】问题处理
    oracle报错【ORA-28000:帐户已被锁定】问题处理
    $(window).load(function(){})和$(document).ready(function(){})的区别
    HttpClientFactory 结合 Polly 轻松实现重试机制
    ocelot 中间件的变化
  • 原文地址:https://www.cnblogs.com/Scx117/p/9206680.html
Copyright © 2011-2022 走看看