zoukankan      html  css  js  c++  java
  • [arc079f]namori grundy

    题意:

    给出一个基环外向树,每个点有一个$sg$值为所有子节点的$mex$值,求是否有设置$sg$值的方案满足条件。

    题解:

    感觉没有B题难。。。听完讲评就会了。。。

    这题栋爷有一种拆环的做法,但是我写的是讲题的时候ckw讲的一种神仙做法,个人感觉容易理解一点qwq

    如果觉得ckw的博客过于神仙可以看看hy写的题解,讲的很清楚qwq(我太垃圾了)

    对了此题还有lzx的一种神仙做法qwq(我太太太垃圾了)

    首先如果是一棵树,显然必定有解,所有叶节点设0,然后取mex即可;

    考虑拓展到基环外向树上,这个树的结构是一个环上的节点和各自的子树构成,那么不妨先对每个子树求出各自的$sg$值(必定有解),然后把环扒出来单独看;

    此时环上的每个节点都有了一个初始的$sg$值,不难发现这个值就是解的下界,现在要做的就是在下界上构造出满足题目要求的解;

    考虑两个在环上相邻的节点$u ightarrow v$,设它们的$sg$值分别为$sg_u$和$sg_v$,分三类考虑:

    1.若$sg_u>sg_v$,那么不用做任何改动,因为$sg_v$已经被包含在$u$的子节点$sg$中了;

    2.若$sg_u=sg_v$,那么把$sg_u$变成$sg_u+1$即可;

    3.若$sg_u<sg_v$,也不需要任何改动。。。因为$sg_v$并不在$sg_u$的范围内;

    所以可以发现两个点只要相等就可以通过+1来调整,只要不等就不需要再调整,所以肯定会有解;

    那么无解情况是什么呢?考虑所有初始值都相等的情况,此时我们需要对隔一个点加一来使得每对相邻点都不相等,环长度为偶数时正好加完,但是当环的长度为奇数的时候加完一圈回去奇偶性就改变了,所以要一直无限的加下去,明显这就是无解的情况。

    暴力dfs模拟上述过程即可

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 using namespace std;
     7 struct edge{
     8     int v,next;
     9 }a[200001];
    10 int n,now,maxn=-2147483647,minn=2147483647,bcc=0,tot=0,sg[200001],head[200001],p[200001];
    11 bool used[200001],huan[200001];
    12 void add(int u,int v){
    13     a[++tot].v=v;
    14     a[tot].next=head[u];
    15     head[u]=tot;
    16 }
    17 void dfs(int u){
    18     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    19         int v=a[tmp].v;
    20         if(!huan[v])dfs(v);
    21     }
    22     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    23         int v=a[tmp].v;
    24         if(!huan[v])used[sg[v]]=true;
    25     }
    26     for(;used[sg[u]];sg[u]++);
    27     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    28         int v=a[tmp].v;
    29         if(!huan[v])used[sg[v]]=false;
    30     }
    31 }
    32 int main(){
    33     memset(head,-1,sizeof(head));
    34     memset(sg,0,sizeof(sg));
    35     scanf("%d",&n);
    36     for(int i=1;i<=n;i++){
    37         scanf("%d",&p[i]);
    38         add(p[i],i);
    39     }
    40     now=1;
    41     for(;!used[now];now=p[now])used[now]=1;
    42     for(;!huan[now];now=p[now])huan[now]=1;
    43     memset(used,0,sizeof(used));
    44     for(int i=1;i<=n;i++){
    45         if(huan[i]){
    46             dfs(i);
    47             bcc++;
    48             maxn=max(maxn,sg[i]);
    49             minn=min(minn,sg[i]);
    50         }
    51     }
    52     if(maxn==minn&&bcc%2)printf("IMPOSSIBLE");
    53     else printf("POSSIBLE");
    54     return 0;
    55 }
  • 相关阅读:
    Java8基础学习之Object类
    Java8基础之equals方法和==的区别
    Spring集成ElasticSearch
    ElasticSearch常用的查询过滤语句
    数据库查看SQL执行计划
    数据库优化总结
    ElasticSearch之集群原理
    curl命令操作ElasticSearch总结
    ElasticSearch相关概念总结
    ElasticSearch基础入门
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9520974.html
Copyright © 2011-2022 走看看