一个类似2-SAT的思想,但是简化了很多。只需要用到并查集实现。

题目描述

企鹅国打算种一批树。所谓树,就是由$N$个结点与$N-1$条边连接而成的连通无向图。企鹅国的国王对于这些树有下列要求:

1. 树没有指定根,但它的形态是给定的(即这$N-1$条边是给出的);
2. 树的每条边上可以放置一朵花(当然也可以不放置)
3. 共$Q$条约束,第$i$组约束规定:标号$u[i]$的结点到标号$v[i]$的结点的简单路径上,花的数量为奇数或偶数。

现在,国王想事先知道他最多能种多少棵不一样的树(两棵树被视为不一样当且仅一棵树中某条边的放花情况与另一棵树不相同)。

输入输出格式

输入格式:

第$1$行两个整数$N,Q$;

接下来$N-1$行,每行两个整数$u,v$,表示$latex u,v$间存在一条边;

接下来$Q$行,每三个整数$u[i],v[i],k[i]$,若$k[i]$为$0$,表示$u[i]$到$v[i]$的简单路径的上花的个数为偶数, 否则为奇数。

输出格式:

一行一个整数,表示能种的不一样的树的种树,对$998244353$取模。

输入输出样例

输入样例#1:

5 3
1 2
1 3
2 4
2 5
1 4 0
1 5 1
1 3 0

输出样例#1:

2

说明

$20\%$的数据:$N, Q\le 20$;

$40\%$的数据:$N, Q\le 100$;

$70\%$的数据:$N, Q\le 5000$;

$100\%$的数据:$N, Q\le 100000, 0\le k[i]\le 1$。

题解:

    这里两点之间的路径为奇数还是偶数与树上唯一一条路径有关,如下图,为了简化问题,我们把奇数和偶数定义为异或和为1和0。

    两点间唯一路径就是这条黄色的路径。我们发现,要保证这条路径的异或和等于给定值,那么它们分别到根的异或和的异或值也是等于给定值的,因为$x\mathrm{xor} x=0$。因此要满足$x$到$y$这条路径的异或和等于给定值,那么只要满足两个点到根的异或和相异或等于给定值就可以了,也就相当于把上面重合的地方消掉了。

    问题转化为异或,我们就不用关心树上的关系了也就是说这棵树废掉了。只需要给每个点一个到根的异或和(0/1)就可以了。

    那么根据给出的询问信息,我们需要知道哪些点必须和哪些点到根的异或和相同,哪些点和哪些点相反。我们要把每个点拆成两个部分,一部分关联相同,另一部分关联的可以不同。样例构造出来就是这样:

    那么一个连通块就代表了同一种到根的异或和,一对连通块(可以发现连通块总是对称的)代表了一对相反的到根的异或和。而每个节点真正到根的异或和是不带'的节点所在的连通块。因此我们只需要保证每个连通块取相同的值,每对连通块取对应的值就可以了。而每对连通块都有两种取值选择,如果相反,就是01/10,如果相同,就是00/11。那么我们一共有2连通块对数种选择。不过有一点要注意,1到根的异或和一定是0,所以有一组是不能任选的。所以我们有2连通块对数-1种选择。

    判断连通块个数,用并查集就好了。

Code:

#include<cstdio>
#include<cstring>
int s[200100];
int my_find(int x)
{
if(s[x]==x)
return x;
return s[x]=my_find(s[x]);
}
void my_union(int x,int y)
{
s[my_find(y)]=my_find(x);
}
bool app[200100];
int qpow(int x,int y)
{
long long ans=1,m=x;
while(y)
{
if(y&1)
ans*=m;
ans%=998244353;
m*=m;
m%=998244353;
y>>=1;
}
return ans;
}
int main()
{
int n,q;
int u,v,w;
scanf("%d%d",&n,&q);
for(int i=1;i<n;++i)
{
s[i]=i;
scanf("%d%d",&u,&v);//可以直接过滤掉
}
for(int i=n;i<=2*n;++i)
s[i]=i;
for(int i=1;i<=q;++i)
{
scanf("%d%d%d",&u,&v,&w);
if(!w)
{
my_union(u,v);//上面图片连边的过程
my_union(u+n,v+n);
}
else
{
my_union(u,v+n);
my_union(u+n,v);
}
}
int cnt=0;
for(int i=1;i<=2*n;++i)
if(!app[my_find(i)])
{
app[my_find(i)]=1;
++cnt;
}
printf("%d\n",qpow(2,cnt-1>>1));//因为所有都统计了,所以要减1除以2
return 0;
}

【2-SAT】【并查集】NOIp模拟题 植树方案 题解的更多相关文章

  1. [Noip模拟题]统计方案​

    题目并不难,想一下就会了,我真的智商持续下降,取模情况下做除法我都没想到逆元. 总之想到逆元就好写了,还是\(meet\ in\ the\ middle\)裸题,数组开不下用\(hash/map\)存 ...

  2. 【BZOJ1998】[HNOI2010]物品调度(并查集,模拟)

    [BZOJ1998][HNOI2010]物品调度(并查集,模拟) 题面 BZOJ,为啥这题都是权限题啊? 洛谷 题解 先不管\(0\)位置是个空,把它也看成一个箱子.那么最终的答案显然和置换循环节的个 ...

  3. poj 2236:Wireless Network(并查集,提高题)

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 16065   Accepted: 677 ...

  4. poj 2524:Ubiquitous Religions(并查集,入门题)

    Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 23997   Accepted:  ...

  5. poj 1611:The Suspects(并查集,经典题)

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 21472   Accepted: 10393 De ...

  6. hrbustoj 1073:病毒(并查集,入门题)

    病毒Time Limit: 1000 MS Memory Limit: 65536 KTotal Submit: 719(185 users) Total Accepted: 247(163 user ...

  7. 【入门OJ】2003: [Noip模拟题]寻找羔羊

    这里可以复制样例: 样例输入: agnusbgnus 样例输出: 6 这里是链接:[入门OJ]2003: [Noip模拟题]寻找羔羊 这里是题解: 题目是求子串个数,且要求简单去重. 对于一个例子(a ...

  8. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

  9. 9.9 NOIP模拟题

    9.9 NOIP模拟题 T1 两个圆的面积求并 /* 计算圆的面积并 多个圆要用辛普森积分解决 这里只有两个,模拟计算就好 两圆相交时,面积并等于中间两个扇形面积减去两个三角形面积 余弦定理求角度,算 ...

随机推荐

  1. ubuntu18.04 蓝牙打开无效,解决办法升级内核

    http://kernel.ubuntu.com/~kernel-ppa/mainline/ 上面的链接是linux内核版本, 蓝牙不管用可能是linux内核版本过低,本人亲自实验过, 升级到4.20 ...

  2. vector向量容器

    vector向量容器不但可以像数组一样对元素进行随机访问,还能在尾部插入元素,是一种简单高效的容器,可以代替数组. vector具有内存自动管理的功能,对于元素的插入和删除,可以动态的调整所占内存. ...

  3. 1-new对象与直接构建对象

    #include <iostream> using namespace std; class A { public: A(){} A (int a){ this->a = a; } ...

  4. Luogu 3265 [JLOI2015]装备购买

    BZOJ 4004 把所有不能相互表示出来的向量都买下,一定能得到最大能买的方案数. 求解线性无关向量可以高斯消元,最后没有变成$0$向量的就是基底. 本题还要求代价最小怎么办?我们只要先把所有向量按 ...

  5. Flask框架 之 上下文管理前戏

    偏函数 自动传递参数 import functools def index(a1,a2): return a1 + a2 # 原来的调用方式 # ret = index(1,23) # print(r ...

  6. Oracle——控制事务

    一.回滚到保留点 使用 SAVEPOINT 语句在当前事务中创建保存点. 使用 ROLLBACK TO SAVEPOINT 语句回滚到创建的保存点. 二.提交或回滚前的数据状态 改变前的数据状态是可以 ...

  7. C# winform中Setting.settings 相关知识点

    1.在Settings.settings文件中定义配置字段.包含字段名.类型.范围.值四部分的属性. 字段名.类型和值类似编程中字段的定义一样使用,不再过多的解释.重点讲一下”范围“字段的含义与区别. ...

  8. 【Head First Java 读书笔记】(六)认识Java API

    第五章 使用Java函数库 ArrayList add(Object elem) remove(int index) remove(Object elem) contains(Object elem) ...

  9. RabbitMQ单机集群搭建出现Error: unable to perform an operation on node 'rabbit1@ClusterNode1'

    参考链接:https://www.cnblogs.com/daryl/archive/2017/10/13/7645749.html 全部步骤和参考链接相同. 前八部都正常,在第九步会报错Error: ...

  10. 【[APIO/CTSC2007]动物园】状压DP

    题目测评:https://www.luogu.org/problemnew/show/P3622 题目描述 新建的圆形动物园是亚太地区的骄傲.圆形动物园坐落于太平洋的一个小岛上,包含一大圈围栏,每个围 ...