20分算法:暴力枚舉每一個點算法
抄題解作的仍是好好寫總結吧api
把紅色視爲0,藍色視爲1spa
假設有一個表格以下:code
A | C | E | G |
---|---|---|---|
B | D | F | H |
根據題設有\(A\bigoplus B\bigoplus C\bigoplus D=C\bigoplus D\bigoplus E\bigoplus F=1\)get
而後有\(A\bigoplus B\bigoplus E\bigoplus F=0\)string
而\(E\bigoplus F\bigoplus G\bigoplus H=1\)it
因此\(A\bigoplus B\bigoplus G\bigoplus H=1\)io
再放到通常性的表格中table
A | ...... | C |
---|---|---|
B | ...... | D |
I | ...... | J |
....... | ...... | ....... |
E | ...... | G |
F | ...... | H |
當C,D處於奇數列的時候,有:class
\(A\bigoplus B\bigoplus C\bigoplus D=0,E\bigoplus F\bigoplus G\bigoplus H=0,B\bigoplus I\bigoplus D\bigoplus J=0\)
因此有:
\(A\bigoplus C\bigoplus I\bigoplus J=0\)
推出
\(A\bigoplus C\bigoplus F\bigoplus H=0\)
即:
\(A\bigoplus H=C\bigoplus F\)
當C,D在偶數列上,有:
\(A\bigoplus B\bigoplus C\bigoplus D=1,E\bigoplus F\bigoplus G\bigoplus H=1,B\bigoplus I\bigoplus D\bigoplus J=1\)
當H在奇數行:
\(1\bigoplus A\bigoplus H=C\bigoplus F\)
當H在偶數行:
\(A\bigoplus H=C\bigoplus F\)
設H座標爲\((i,j)\),A座標爲\((1,1)\)
則有:
\(if(i\ mod\ 2==0\ and\ j\ mod \ 2==0) \ 1\bigoplus(1,1)\bigoplus(i,j) ==(1,j)\bigoplus(i,1)\)
\(else\ (1,1)\bigoplus(i,j) ==(1,j)\bigoplus(i,1)\)
而顯然若是肯定了第一排,第一列,那麼能夠肯定整張圖。
因此能夠枚舉\((1,1)\)的值,而後合併全部相關的集合,去掉已知點的集合,剩下的集合個數爲\(cnt\),則答案爲\(2^{cnt}\)。
把(1,1)爲0,1的答案加起來便可
合併集合的時候使用擴展域並查集維護到根節點的異或值。
#include <cstdio> #include <cstring> #include <cstdlib> #define R register #define ll long long const int MAXN=1e6+10; const int Mod=1e9; inline int read() { int x=0,f=1; char a=getchar(); for(;a>'9'||a<'0';a=getchar()) if(a=='-') f=-1; for(;a>='0'&&a<='9';a=getchar()) x=x*10+a-'0'; return x*f; } int n,m,k,flg=-1,cnt,Size; int fa[MAXN]; int X[MAXN],Y[MAXN],Z[MAXN]; inline int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } inline void merge(int x,int y) { int fx=find(x),fy=find(y); fa[fx]=fy;cnt-=fx!=fy; } inline void Init() { n=read();m=read();k=read(); Size=n+m-1; for(R int i=1;i<=k;i++) { X[i]=read();Y[i]=read();Z[i]=read(); if(X[i]==1&&Y[i]==1) flg=Z[i]; } } inline int id(int x) { return x==1?1:m+x-1; } int vis[MAXN]; int ans=0; inline void Solve(bool delta) { for(R int i=1;i<=Size*2;i++) fa[i]=i; cnt=Size*2; for(R int i=1;i<=k;i++) { int a=X[i],b=Y[i]; if(a==1&&b==1) continue; if(a%2==0&&b%2==0) { if(1^delta^Z[i]) { merge(id(a),b+Size);merge(id(a)+Size,b); } else { merge(id(a),b);merge(id(a)+Size,b+Size); } } else { if(delta^Z[i]) { merge(id(a),b+Size); merge(id(a)+Size,b); } else { merge(id(a),b); merge(id(a)+Size,b+Size); } } if(find(b)==find(b+Size)||find(id(a))==find(id(a)+Size)) { printf("0\n"); exit(0); } } memset(vis,0,sizeof(vis)); cnt--; vis[find(1)]=1; for(R int i=1;i<=k;i++) { if(X[i]==1&&vis[find(Y[i])]==0) { vis[find(Y[i])]=1; cnt--; } else if(Y[i]==1&&vis[find(id(X[i]))]==0) { vis[find(id(X[i]))]=1; cnt--; } } cnt>>=1; int tmp=1; for(R int i=1;i<=cnt;i++) tmp=(tmp<<1)>=Mod?(tmp<<1)-Mod:(tmp<<1); ans=ans+tmp>=Mod?ans+tmp-Mod:ans+tmp; } int main() { Init(); if(flg==-1) Solve(0),Solve(1); if(flg==0) Solve(0); if(flg==1) Solve(1); printf("%d\n",ans); return 0; }