[BZOJ5303] [HAOI2018] 反色游戏
題目鏈接
LOJ:https://loj.ac/problem/2524
BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303
洛谷:https://www.luogu.org/problemnew/show/P4494
Solution
精神污染
假設(shè)所有點都是連通的,很顯然如果黑點個數(shù)為奇數(shù)個則無解,否則可以證明一定有解。
那么隨便整出一棵生成樹,然后反色一些邊使其合法,顯然一棵樹只有一種情況。
考慮非樹邊的貢獻,如果非樹邊不反色顯然無影響,否則可以把這條邊兩個端點連成的鏈上所有邊都反色,那么可以發(fā)現(xiàn)當(dāng)前方案還是合法的。
那么每條非樹邊都可選可不選,總方案數(shù)就是\(2^{m-n+1}\)。
注意到原圖不一定聯(lián)通,考慮每個聯(lián)通塊,方案數(shù)相乘,可以得到總方案數(shù)為\(2^{m-n+p}\),其中\(p\)為聯(lián)通塊個數(shù)。
注意每個聯(lián)通塊都必須合法,否則無解。
對于刪點,我們分情況討論:
- 如果當(dāng)前點是孤立的,對答案無影響。
- 當(dāng)前點不是割點,那么對答案影響無非就是點數(shù)少\(1\),邊數(shù)少了點,直接算就好了。
- 對于割點,我們需要判割完之后剩下的聯(lián)通塊合不合法,答案也差不多。
這題最難寫的地方就是判無解....不過據(jù)說建圓方樹好寫點?
細節(jié)很多...
#include<bits/stdc++.h> using namespace std;void read(int &x) {x=0;int f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; }void print(int x) {if(x<0) putchar('-'),x=-x;if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar(' ');}#define lf double #define ll long long const int maxn = 2e5+10; const int inf = 1e9; const lf eps = 1e-8; const int mod = 1e9+7;char s[maxn]; int n,m,head[maxn],tot,dfn[maxn],dfn_cnt,low[maxn],bo[maxn],cnt[maxn],rt,c[maxn],is[maxn],bel[maxn],deg[maxn],sz[maxn],pw[maxn],siz[maxn]; struct edge{int to,nxt;}e[maxn<<1];void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot,deg[v]++;} void ins(int u,int v) {add(u,v),add(v,u);}void tarjan(int x,int fa) {dfn[x]=low[x]=++dfn_cnt,bel[x]=rt,bo[x]=1,siz[x]=sz[x];int flag=0;for(int v,i=head[x];i;i=e[i].nxt) {if((v=e[i].to)==fa) continue;flag++;if(!dfn[v]) tarjan(v,x),low[x]=min(low[x],low[v]),sz[x]+=sz[v];else {low[x]=min(low[x],dfn[v]);continue;}if(low[v]>=dfn[x]) bo[x]&=!(sz[v]&1),cnt[x]++,is[x]=1,siz[x]+=sz[v];}if(fa) cnt[x]++;if(!flag) is[x]=1; }void solve() {read(n),read(m);for(int i=1,x,y;i<=m;i++) read(x),read(y),ins(x,y);scanf("%s",s+1);for(int i=1;i<=n;i++) sz[i]=c[i]=s[i]-'0';pw[0]=1;for(int i=1;i<=m;i++) pw[i]=2ll*pw[i-1]%mod;int p=0,odd=0;for(int i=1;i<=n;i++)if(!dfn[i]) rt=i,tarjan(i,0),p++,odd+=sz[i]&1;for(int i=1;i<=n;i++) bo[i]&=!((sz[bel[i]]-siz[i])&1);write(odd?0:pw[m-n+p]);for(int i=1;i<=n;i++) {if(!deg[i]) write(odd-sz[i]?0:pw[m-n+p]);else if(!is[i]) write(odd-(sz[bel[i]]&1)+((sz[bel[i]]-c[i])&1)?0:pw[m-deg[i]-n+p+1]);else write(bo[i]&&!(odd-(sz[bel[i]]&1))?pw[m-deg[i]-n+cnt[i]+p]:0); }puts(""); }#define clr(x) memset(x,0,4*(n+5))void clear() {clr(dfn),clr(low),clr(bel),clr(deg);clr(sz),clr(bo),clr(is),clr(head),clr(cnt),clr(siz);tot=0; }int main() {int t;read(t);while(t--) solve(),clear();return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/hbyer/p/10649060.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的[BZOJ5303] [HAOI2018] 反色游戏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。