[Luogu4494] [BZOJ5303] [LOJ2524]

LOJ有数据就是好

原题解,主要是代码参考

对于每一个联通块(n个点),其他的边一开始随便选,只需要n-1条边就可以确定最终结果.

所以设\(cnt\)为联通块数 , 答案为 \(2^{m-n+cnt}\)

还有就是有解的情况必须是黑点个数为偶数,还要注意有删掉这个点可能使无解变有解,这比从有解变无解更难想

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define debug(...) fprintf(stderr,__VA_ARGS__)
  6. #define Debug(x) cout<<#x<<"="<<x<<endl
  7. using namespace std;
  8. typedef long long LL;
  9. const int INF=1e9+7;
  10. inline LL read(){
  11. register LL x=0,f=1;register char c=getchar();
  12. while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
  13. while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
  14. return f*x;
  15. }
  16. const int MAXN=100005;
  17. const int MAXM=200005;
  18. const int mod=1e9+7;
  19. struct Edge{
  20. int v,w,c,next;
  21. }e[MAXM];
  22. int first[MAXN],Ecnt=1;
  23. inline void Add_edge(int u,int v,int w=0,int c=0){
  24. e[++Ecnt]=(Edge){v,w,c,first[u]};
  25. first[u]=Ecnt;
  26. }
  27. int ctg[MAXN],size[MAXN],sub[MAXN],low[MAXN],dfn[MAXN],deg[MAXN],cut[MAXN],pow2[MAXN];
  28. bool flag[MAXN];
  29. char S[MAXN];
  30. int n,m,T,ans,odd,dft,cnt,rt;
  31. inline void clear(){
  32. memset(size,0,sizeof size);
  33. memset(deg,0,sizeof deg);
  34. memset(sub,0,sizeof sub);
  35. memset(cut,0,sizeof cut);
  36. memset(low,0,sizeof low);
  37. memset(dfn,0,sizeof dfn);dft=0;
  38. memset(first,0,sizeof first);Ecnt=0;
  39. cnt=0,odd=0;
  40. }
  41. inline void tarjan(int u,int pre=0){
  42. low[u]=dfn[u]=++dft;
  43. flag[u]=1;
  44. size[u]=(S[u]=='1');//算黑点数量
  45. ctg[u]=rt;//这种情况下方便后面调用
  46. for(int i=first[u];i;i=e[i].next){
  47. int v=e[i].v;
  48. if(!dfn[v]){
  49. tarjan(v,u);
  50. size[u]+=size[v];
  51. if(low[v]>=dfn[u]){
  52. cut[u]++;
  53. flag[u]&=((size[v]&1)==0);//子树不合法可以直接标记
  54. sub[u]+=size[v];
  55. }
  56. else low[u]=min(low[u],low[v]);
  57. }
  58. else if (v!=pre) low[u]=min(low[u],dfn[v]);
  59. }
  60. if(!pre) cut[u]--;//删掉u以后能增加几个连通分量
  61. }
  62. int main(){
  63. pow2[0]=1;
  64. for(int i=1;i<MAXN;i++) pow2[i]=(pow2[i-1]<<1)%mod;
  65. T=read();
  66. while(T--){
  67. n=read(),m=read();
  68. clear();
  69. for(int i=1;i<=m;i++){
  70. int x=read(),y=read();
  71. Add_edge(x,y);
  72. Add_edge(y,x);
  73. deg[x]++,deg[y]++;
  74. }
  75. scanf("%s",S+1);
  76. for(int i=1;i<=n;i++) if(!dfn[i]){
  77. //ctgn++;//这里不适合这样用
  78. rt=i,cnt++;
  79. tarjan(i);
  80. odd+=size[i]&1;
  81. }
  82. ans=m-n+cnt;
  83. printf("%d",odd?0:pow2[ans]);//只要有偶数个黑点就是无解的
  84. for(int i=1;i<=n;i++){
  85. if(!deg[i]) printf(" %d",odd-size[i]==0?pow2[ans]:0);//以后复杂题目估计都得写成这样
  86. else{
  87. //子树合法 父亲那一块合法 也许不合法变为合法
  88. if((flag[i]) && (((size[ctg[i]]-(S[i]=='1')-sub[i])&1)==0) && (odd-(size[ctg[i]]&1)==0))
  89. printf(" %d",pow2[ans-deg[i]+1+cut[i]]);
  90. else printf(" 0");
  91. }
  92. }
  93. printf("\n");
  94. }
  95. }

[HAOI2018]反色游戏的更多相关文章

  1. 【BZOJ5303】[HAOI2018]反色游戏(Tarjan,线性基)

    [BZOJ5303][HAOI2018]反色游戏(Tarjan,线性基) 题面 BZOJ 洛谷 题解 把所有点全部看成一个\(01\)串,那么每次选择一条边意味着在这个\(01\)串的基础上异或上一个 ...

  2. bzoj 5393 [HAOI2018] 反色游戏

    bzoj 5393 [HAOI2018] 反色游戏 Link Solution 最简单的性质:如果一个连通块黑点个数是奇数个,那么就是零(每次只能改变 \(0/2\) 个黑点) 所以我们只考虑偶数个黑 ...

  3. P4494 [HAOI2018]反色游戏

    P4494 [HAOI2018]反色游戏 题意 给你一个无向图,图上每个点是黑色或者白色.你可以将一条边的两个端点颜色取反.问你有多少种方法每个边至多取反一次使得图上全变成白色的点. 思路 若任意一个 ...

  4. 【loj#2524】【bzoj5303】 [Haoi2018]反色游戏(圆方树)

    题目传送门:loj bzoj 题意中的游戏方案可以转化为一个异或方程组的解,将边作为变量,点作为方程,因此若方程有解,方程的解的方案数就是2的自由元个数次方.我们观察一下方程,就可以发现自由元数量=边 ...

  5. [BZOJ5303] [HAOI2018] 反色游戏

    题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...

  6. [BZOJ5303][HAOI2018]反色游戏(Tarjan)

    暴力做法是列异或方程组后高斯消元,答案为2^自由元个数,可以得60分.但这个算法已经到此为止了. 从图论的角度考虑这个问题,当原图是一棵树时,可以从叶子开始唯一确定每条边的选择情况,所以答案为1. 于 ...

  7. bzoj 5303: [Haoi2018]反色游戏

    Description Solution 对于一个有偶数个黑点的连通块,只需要任意两两配对,并把配对点上的任一条路径取反,就可以变成全白了 如果存在奇数个黑点的连通块显然无解,判掉就可以了 如果有解, ...

  8. Luogu4494 [HAOI2018]反色游戏 【割顶】

    首先发现对于一个联通块有奇数个黑点,那么总体来说答案无解.这个很容易想,因为对每个边进行操作会同时改变两个点的颜色,异或值不变. 然后一个朴素的想法是写出异或方程进行高斯消元. 可以发现高斯消元的过程 ...

  9. 洛谷P4494 [HAOI2018]反色游戏(tarjan)

    题面 传送门 题解 我们先来考虑一个联通块,这些关系显然可以写成一个异或方程组的形式,形如\(\oplus_{e\in edge_u}x_e=col_u\) 如果这个联通块的黑色点个数为奇数,那么显然 ...

随机推荐

  1. 【转】LVS负载均衡之session解决方案 持久连接

    原文地址:http://minux.blog.51cto.com/8994862/1744761 1. 持久连接是什么? 1.1 在LVS中,持久连接是为了用来保证当来自同一个用户的请求时能够定位到同 ...

  2. 面试题:SpringMVC的工作流程

    SpringMVC是当今最主流的Web MVC框架,没有之一,要做一名合格的JavaWeb工程师,学好它势在必行! 与Struts2原理不同,SpringMVC是通过最基础最传统的servlet来实现 ...

  3. PC端QT源码编译

    转载:http://blog.sina.com.cn/s/blog_c2b97b1d01016x1i.html 1.下载源码(前面已经提到了) 选择合适自己的源码. 先用"uname -a& ...

  4. 19. AUTO INCREMENT 字段

    Auto-increment 会在新记录插入表中时生成一个唯一的数字. AUTO INCREMENT 字段 我们通常希望在每次插入新记录时,自动地创建主键字段的值. 我们可以在表中创建一个 auto- ...

  5. p2148 [SDOI2009]E&D

    传送门 分析 https://www.luogu.org/blog/flashblog/solution-p2148 代码 #include<bits/stdc++.h> using na ...

  6. github如何上传代码

    别人写的太好了,没必要重写.备份给自己参看. 1.https://www.cnblogs.com/zlxbky/p/7727895.html 2.https://blog.csdn.net/pql92 ...

  7. Row_Number() OVER()函数使用举例

    语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN) 简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW ...

  8. XE下创建及调用Frame

    1.创建Form1: 2.创建FMXFrame(New -> Other->Delphi Files -> FMXFrame); // 单元名为UnitFrame,窗体名为frm  ...

  9. [.net 多线程]Semaphore信号量

    信号量(Semaphore)是一种CLR中的内核同步对象.与标准的排他锁对象(Monitor,Mutex,SpinLock)不同的是,它不是一个排他的锁对象,它与SemaphoreSlim,Reade ...

  10. 基于zookeeper实现高性能分布式锁

    实现原理:利用zookeeper的持久性节点和Watcher机制 具体步骤: 1.创建持久性节点 zkLock 2.在此父节点下创建子节点列表,name按顺序定义 3.Java程序获取该节点下的所有顺 ...