2018CodeM復賽
阿新 • • 發佈:2018-07-09
。。 圖片 long sca 分享 \n 生成樹 聯通塊 bit
待續。。。
官方題解
前言:這場比賽打得非常坎坷,剛開始以為7:30開始,結果遲進賽場。然後因為是在家裏打,鍵盤好難用啊=_=
嗶——地一聲,電腦關機,發現充電線沒插好。。。插好之後,肚子餓->去翻櫃子吃東西,所以解題速度就變成這樣了?!
A
DP
B
水水的二分題,我竟然在二分判斷可行解時用了tarjan,雖然也卡過去了,但明顯用拓撲序更優
C
其實就是先將已確定的邊相連,同時求出所有邊相連後的聯通塊/生成樹個數(並查集維護)s1
遍歷之前由確定的邊相連所得到的森林,並判斷是否已有矛盾,同時標記顏色。求出當前的聯通塊/生成樹個數s2
則2^(s2-s1)即為答案,自己模擬下應該就能理解
- 題解
#include<bits/stdc++.h> #define rep(i,j,k) for(int i=(int)j;i<=(int)k;i++) #define per(i,j,k) for(int i=(int)j;i>=(int)k;i--) #define pii pair<int,int> using namespace std; typedef long long LL; typedef double db; const int N=110000; const int P=998244353; int n,m; int head[N],np[N<<1],p[N<<1],col[N<<1],tot; int w[N],fa[N]; bool wei=0; inline int get(int x){if(x==fa[x])return x;return fa[x]=get(fa[x]);} int kk=0; void dfs(int x,int c){ w[x]=c; if(wei)return; for(int u=head[x];u;u=np[u]){ int y=p[u]; int d=col[u]; if(w[y]==-1)dfs(y,c^d); else{ if((w[x]^w[y])!=d)wei=1; } } } int main(){ scanf("%d%d",&n,&m); rep(i,1,n)fa[i]=i;kk=n; rep(i,1,m){ int a,b,c;scanf("%d%d%d",&a,&b,&c); if(get(a)^get(b)){ fa[get(a)]=get(b); --kk; } if(c==-1)continue; ++tot;p[tot]=b;np[tot]=head[a];head[a]=tot;col[tot]=c; ++tot;p[tot]=a;np[tot]=head[b];head[b]=tot;col[tot]=c; } memset(w,-1,sizeof w); int rp=0; rep(i,1,n)if(w[i]==-1){ dfs(i,0); ++rp; } if(wei){ printf("0\n"); return 0; } int ans=1; cerr<<rp<<" "<<kk<<endl; rep(i,1,rp-kk)ans=ans*2ll%P; printf("%d\n",ans); return 0; }
2018CodeM復賽