HAOI2018 反色游戏
这个题一开始他们说什么列异或方程组我也不懂……根据学姐告诉我的结论,如果联通块内有一棵树的话,那么其他的非树边反转或者不反转都行,反正树是能给你还原回去的。不过如果有奇数个黑点是不行的。
根据这个结论,记录联通块个数为tot,那么不删点的时候答案就是\(2^{m-n+tot}\)
然后对于删点……和yyb大神学的……如果这个点是割点,那么首先我们看它所连接的联通块中有没有有奇数个黑点的,如果有就不行。
之后再看它上面的联通块中是否有奇数个黑点,有就不行。
如果这个联通块外也有奇数个黑点……还是不行……
否则的话答案就是在原来的基础上,减去点度,加上1,再加上获得的新联通块个数,原理和上面是一样的。
注意如果是根的话获得的新联通块个数要-1,因为上面没了。
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int M = 100005;
const int mod = 1e9+7;
int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}
struct edge
{
int next,to,from;
}e[M<<1];
int n,m,head[M],ecnt,dfn[M],low[M],vis[M],idx,root,T;
int sum[M],c[M],d[M],f[M],deg[M],po[M<<1],a[M],val,tot,x,y;
char s[M];
void add(int x,int y){e[++ecnt] = {head[x],y,x},head[x] = ecnt,deg[y]++;}
void clear()
{
ecnt = idx = val = tot = 0;
rep(i,1,n) head[i] = dfn[i] = low[i] = deg[i] = d[i] = c[i] = f[i] = 0;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++idx,vis[x] = root,sum[x] = a[x];
for(int i = head[x];i;i = e[i].next)
{
int t = e[i].to;
if(!dfn[t])
{
tarjan(t),sum[x] += sum[t];
low[x] = min(low[x],low[t]);
if(low[t] >= dfn[x]) d[x] |= (sum[t] & 1),c[x]++,f[x] += sum[t];
}
else low[x] = min(low[x],dfn[t]);
}
if(x == root) c[x]--;
}
int main()
{
po[0] = 1;
rep(i,1,(M<<1)-1) po[i] = (po[i-1] << 1) % mod;
T = read();
while(T--)
{
n = read(),m = read(),clear();
rep(i,1,m) x = read(),y = read(),add(x,y),add(y,x);
scanf("%s",s+1);
rep(i,1,n) a[i] = s[i] - '0';
rep(i,1,n) if(!dfn[i]) root = i,tarjan(i),tot++,val += sum[i] & 1;
val ? printf("0 ") : printf("%d ",po[m-n+tot]);
rep(i,1,n)
{
if(d[i]) printf("0 ");
else if(val - (sum[vis[i]] & 1)) printf("0 ");
else if((sum[vis[i]] - a[i] - f[i]) & 1) printf("0 ");
else printf("%d ",po[m-n+tot-deg[i]+1+c[i]]);
}
enter;
}
return 0;
}
当你意识到,每个上一秒都成为永恒。