[Luogu4494] [BZOJ5303] [LOJ2524]

LOJ有数据就是好

原题解,主要是代码参考

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

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

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

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
} const int MAXN=100005;
const int MAXM=200005;
const int mod=1e9+7; struct Edge{
int v,w,c,next;
}e[MAXM];
int first[MAXN],Ecnt=1;
inline void Add_edge(int u,int v,int w=0,int c=0){
e[++Ecnt]=(Edge){v,w,c,first[u]};
first[u]=Ecnt;
} int ctg[MAXN],size[MAXN],sub[MAXN],low[MAXN],dfn[MAXN],deg[MAXN],cut[MAXN],pow2[MAXN];
bool flag[MAXN];
char S[MAXN];
int n,m,T,ans,odd,dft,cnt,rt; inline void clear(){
memset(size,0,sizeof size);
memset(deg,0,sizeof deg);
memset(sub,0,sizeof sub);
memset(cut,0,sizeof cut);
memset(low,0,sizeof low);
memset(dfn,0,sizeof dfn);dft=0;
memset(first,0,sizeof first);Ecnt=0;
cnt=0,odd=0;
} inline void tarjan(int u,int pre=0){
low[u]=dfn[u]=++dft;
flag[u]=1;
size[u]=(S[u]=='1');//算黑点数量
ctg[u]=rt;//这种情况下方便后面调用
for(int i=first[u];i;i=e[i].next){
int v=e[i].v;
if(!dfn[v]){
tarjan(v,u);
size[u]+=size[v];
if(low[v]>=dfn[u]){
cut[u]++;
flag[u]&=((size[v]&1)==0);//子树不合法可以直接标记
sub[u]+=size[v];
}
else low[u]=min(low[u],low[v]);
}
else if (v!=pre) low[u]=min(low[u],dfn[v]);
}
if(!pre) cut[u]--;//删掉u以后能增加几个连通分量
} int main(){
pow2[0]=1;
for(int i=1;i<MAXN;i++) pow2[i]=(pow2[i-1]<<1)%mod;
T=read();
while(T--){
n=read(),m=read();
clear();
for(int i=1;i<=m;i++){
int x=read(),y=read();
Add_edge(x,y);
Add_edge(y,x);
deg[x]++,deg[y]++;
}
scanf("%s",S+1);
for(int i=1;i<=n;i++) if(!dfn[i]){
//ctgn++;//这里不适合这样用
rt=i,cnt++;
tarjan(i);
odd+=size[i]&1;
}
ans=m-n+cnt;
printf("%d",odd?0:pow2[ans]);//只要有偶数个黑点就是无解的
for(int i=1;i<=n;i++){
if(!deg[i]) printf(" %d",odd-size[i]==0?pow2[ans]:0);//以后复杂题目估计都得写成这样
else{
//子树合法 父亲那一块合法 也许不合法变为合法
if((flag[i]) && (((size[ctg[i]]-(S[i]=='1')-sub[i])&1)==0) && (odd-(size[ctg[i]]&1)==0))
printf(" %d",pow2[ans-deg[i]+1+cut[i]]);
else printf(" 0");
}
}
printf("\n");
}
}

最新文章

  1. C++开始前篇,深入编译链接(3)
  2. code标签和pre标签
  3. JMS中的消息通信模型
  4. Mock方法介绍
  5. miniUI datagrid 获取序号
  6. 20个Linux服务器安全强化建议(二)
  7. JS中数组的操作
  8. [转载] nosql 数据库的分布式算法
  9. dbcp基本配置和重连配置 -- mysql 8小时自动断开连接的问题
  10. JavaWeb学习记录(十九)——jstl自定义标签库之传统标签
  11. 从地址栏输入url到显示页面都发生了什么?
  12. centos7安装mplayer以及出现的各种问题
  13. android——拍照,相册图片剪切其实就这么简单
  14. scala模式匹配与样例类
  15. [Linux] PHP程序员玩转Linux系列-自动备份与SVN
  16. 更换yum源
  17. 欧朋Opera 浏览器(打不开百度)提示“您的连接不是私密连接”,解决办法
  18. HDFS及其各组件的机制
  19. 表格重新加载 where 携带上次值问题
  20. webpack的使用一

热门文章

  1. 数据结构》关于差分约束的两三事(BZOJ2330)
  2. Eclipse导入tomcat服务器
  3. memcache 随笔
  4. oralce错误总结
  5. 手打的table
  6. MVC复杂类型的模型绑定
  7. css总结2:Flex 布局教程:Flex 语法(转)
  8. 升级Ubuntu 12.04下的gcc到4.7
  9. Densely Connected Convolutional Networks(緊密相連卷積網絡)
  10. java实现wc功能