AT5800 [AGC043C] Giant Graph 題解
阿新 • • 發佈:2021-10-28
Link.
Description.
有三個無向圖 \(G_1,G_2,G_3\),均有 \(n\) 個點。
以這三個圖構造一個有 \(n^3\) 個點的無向圖 \(G\),構造方式如下:
- \(\forall (u,v)\in G_1,\forall x,y\in[1,n],((u,x,y),(v,x,y))\in G\)
- \(\forall (u,v)\in G_2,\forall x,y\in[1,n],((x,u,y),(x,v,y))\in G\)
- \(\forall (u,v)\in G_3,\forall x,y\in[1,n],((x,y,u),(x,y,v))\in G\)
新圖 \((a,b,c)\) 點權是 \(10^{18(a+b+c)}\)
問最大獨立集。
Solution.
考慮 \(10^{18}\) 是一個很大的數,可以把它當作 \(+\infty\)。
這樣我們的貪心選擇 \(a+b+c\) 最大的點貪心選上,這樣肯定是正確的。
我們對於三張圖,可以給邊定向,指定大的指向小的。
對於一張圖,最優決策可以看成是 \(SG\) 函式。
三張圖互不干擾 \(SG\) 函式就是 \(\oplus\),可以直接 FWT
。
Coding.
點選檢視程式碼
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{ #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; } template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}} const int P=998244353,N=100005; inline int ksm(int x,int q=P-2) {int r=1;for(;q;q>>=1,x=1ll*x*x%P) if(q&1) r=1ll*r*x%P;return r;} int n,m,sg[3][N],tn[1025],sz[3][1025];vector<int>ef[N]; inline void solve(int *a) { read(m);for(int i=1;i<=n;i++) ef[i].clear(); for(int i=1,x,y;i<=m;i++) read(x,y),ef[min(x,y)].push_back(max(x,y)); for(int i=n;i>=1;i--) { for(int x:ef[i]) tn[a[x]]=1; for(int w=0;;w++) if(!tn[w]) {a[i]=w;break;} for(int x:ef[i]) tn[a[x]]=0; } } inline void FWT(int n,int *a,char fg) { for(int d=1;d<n;d<<=1) for(int i=0;i<n;i+=d+d) for(int j=i;j<i+d;j++) {int x=a[j],y=a[j|d],w=fg?(P+1)>>1:1;a[j]=1ll*(x+y)*w%P,a[j|d]=1ll*(x-y+P)*w%P;} } int main() { read(n);for(int i=0;i<3;i++) solve(sg[i]); int mx=0;for(int i=0;i<3;i++) for(int j=1;j<=n;j++) mx=max(mx,sg[i][j]); int T=1,pw=1000000000000000000%P;while(T<=mx) T<<=1; for(int i=0;i<3;i++) for(int j=1;j<=n;j++) sz[i][sg[i][j]]=(sz[i][sg[i][j]]+ksm(pw,j))%P; FWT(T,sz[0],0),FWT(T,sz[1],0),FWT(T,sz[2],0); for(int i=0;i<T;i++) sz[0][i]=1ll*sz[0][i]*sz[1][i]%P*sz[2][i]%P; return FWT(T,sz[0],1),printf("%d\n",sz[0][0]),0; }