题解 【UR #21】挑战最大团
Solution
我们可以知道以下一些性质:
-
优美的图任意导出子图都是优美的
-
优美的图的补图也是优美的
-
优美的图与其补题最多一个联通
-
优美的图直径 \(\le 2\)
那么,我们求最大独立集就可以用分治解决,注意需要使用启发式分裂。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 998244353
#define MAXN 8005
template <typename T> void read (T &x){char c = getchar ();x = 0;int f = 1;while (c < '0' || c > '9') f = (c == '-' ? -1 : 1),c = getchar ();while (c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar ();x *= f;}
template <typename T,typename ... Args> void read (T &x,Args& ... args){read (x),read (args...);}
template <typename T> void write (T x){if (x < 0) x = -x,putchar ('-');if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
int getnum (char x){
if (x >= '0' && x <= '9') return x - '0';
return x - 'A' + 10;
}
bool mp[MAXN][MAXN];
int n,kas,deg[MAXN],vis[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}
void get_ans (vector <int> &a,int len,vector <int> &ans) ;
int fuckit (vector <int> &a,int len,vector <int> &ans,int st,int op){
vis[st] = ++ kas;
for (Int i = 1;i <= len;++ i) if (mp[st][a[i]] == (op ^ 1)){
vis[a[i]] = kas;
for (Int j = 1;j <= len;++ j) if (mp[a[i]][a[j]] == (op ^ 1)) vis[a[j]] = kas;
}
bool flg = 0;
for (Int i = 1;i <= len;++ i) if (vis[a[i]] != kas) flg = 1;
if (!flg) return 0;
vector <int> al,ar,ansl,ansr;int lenl = 0,lenr = 0;
al.push_back (0),ar.push_back (0);
for (Int i = 1;i <= len;++ i) if (vis[a[i]] == kas) al.push_back (a[i]),++ lenl;else ar.push_back (a[i]),++ lenr;
ansl.resize (lenl + 1),ansr.resize (lenr + 1);
for (Int i = 1;i <= lenl;++ i) for (Int j = 1;j <= lenr;++ j) if (mp[al[i]][ar[j]]) mp[al[i]][ar[j]] = 0,deg[al[i]] --,deg[ar[j]] --;
for (Int i = 1;i <= lenl;++ i) ansl[i] = 0;for (Int i = 1;i <= lenr;++ i) ansr[i] = 0;
get_ans (al,lenl,ansl),get_ans (ar,lenr,ansr);
for (Int i = 1;i <= lenl;++ i) Add (ans[i],ansl[i]);
for (Int i = 1;i <= lenr;++ i) Add (ans[i],ansr[i]);
if (op == 0) ;
else for (Int i = 1;i <= lenl;++ i) for (Int j = 1;j <= lenr;++ j) Add (ans[i + j],mul (ansl[i],ansr[j]));
return 1;
}
#define pii pair<int,int>
void get_ans (vector <int> &a,int len,vector <int> &ans){
if (len == 1){
ans[1] = 1;
return ;
}
pii fuc[2];fuc[0].first = fuc[1].first = 1e9;
for (Int i = 1;i <= len;++ i) chkmin (fuc[0],{deg[a[i]],a[i]}),chkmin (fuc[1],{len - deg[a[i]] - 1,a[i]});
int opt = (fuc[0].first > fuc[1].first);
if (!fuckit (a,len,ans,fuc[opt].second,opt)) fuckit (a,len,ans,fuc[opt ^ 1].second,opt);
}
char s[MAXN];
signed main(){
read (n);
for (Int i = 1;i < n;++ i){
scanf ("%s",s);
for (Int j = 0;j < n - i;++ j) mp[i][i + j + 1] = mp[i + j + 1][i] = (getnum (s[j / 4]) >> (j & 3) & 1);
}
for (Int i = 1;i <= n;++ i) for (Int j = 1;j <= n;++ j) deg[i] += mp[i][j];
vector <int> sa,ans;sa.resize (n + 1),ans.resize (n + 1);
for (Int i = 1;i <= n;++ i) sa[i] = i;get_ans (sa,n,ans);
for (Int i = 1;i <= n;++ i) write (ans[i]),putchar (' ');putchar ('\n');
return 0;
}

浙公网安备 33010602011771号