AGC043C Giant Graph

Link
很显然有一个贪心:每次选能选的权值最大的点。
那么我们可以把所有边定向,从\(x+y+z\)小的连向大的,然后就可以得到一个DAG。
那么一个点在最优解中当且仅当其出点都不在最优解,一个点不在最优解中当且仅当其出点存在一个在最优解中的点。
这个形式和一般的博弈图完全一致,因此答案就是所有必败态的权值和。
同时注意到三维是相互独立的,因此我们可以把原问题看做是三维上独立游戏的和。
那么答案就是\(\sum\limits_{f_0(x)\operatorname{xor}f_1(y)\operatorname{xor}f_2(z)=0}base^{x+y+z}\)
注意到\(f(x)\le\sqrt{|E|}\),因此直接暴力枚举即可。

#include<cctype>
#include<cstdio>
#include<vector>
const int N=100007,M=512,P=998244353,base=1000000000000000000%P;
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int n;
struct graph
{
    int f[N],g[M],vis[M];std::vector<int>e[N];
    void input()
    {
	for(int m=read(),u,v;m;--m) u=read(),v=read(),e[std::min(u,v)].push_back(std::max(u,v));
	for(int u=n;u;--u)
	{
	    for(int v:e[u]) vis[f[v]]=1;
	    while(vis[f[u]]) ++f[u];
	    for(int v:e[u]) vis[f[v]]=0;
	}
	for(int i=1,x=1;i<=n;++i) x=mul(x,base),inc(g[f[i]],x);
    }
}a[3];
int main()
{
    n=read();int ans=0;
    for(int i=0;i<3;++i) a[i].input();
    for(int i=0;i<512;++i) for(int j=0;j<512;++j) inc(ans,1ll*a[0].g[i]*a[1].g[j]%P*a[2].g[i^j]%P);
    printf("%d",ans);
}
posted @ 2020-05-03 13:27  Shiina_Mashiro  阅读(268)  评论(0编辑  收藏  举报