题解 P7146 【[THUPC2021 初赛]独立】
瞎几把写的乱搞。
首先拿那个 maker 玩一玩,可以发现环数一般都很小,随了蛮久好像最大就 7 的样子。
所以可以把涉及到的 14 个点拿出来,枚举选/不选,树形背包。
然后这样是
然后可以发现一般是不连通的,有效的连通块大小大概是几千的样子(具体多少我不记得了)然后只对这些连通块 dp,印象中可以跑到比较后的点了,但还是过不去。
然后可以发现每条环边都是返祖边的,那么有效枚举量只有
复杂度就是
代码很丑,修修补补过的。
#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define mp make_pair
#define pi pair<int, int>
#define pb push_back
#define vi vector<int>
#define int long long
int gi() {
char cc = getchar() ; int cn = 0, flus = 1 ;
while( cc < '0' || cc > '9' ) { if( cc == '-' ) flus = - flus ; cc = getchar() ; }
while( cc >= '0' && cc <= '9' ) cn = cn * 10 + cc - '0', cc = getchar() ;
return cn * flus ;
}
const int inf = 1e14 + 7 ;
const int P = 1e9 + 7 ;
const int N = 2e5 + 5 ;
const int M = 30 ;
int n, m, cnt, A[N], Ans, dp[N][2], zk[N], zt[N], g[N], rt[N] ;
int head[N], fa[N], st[M], top, c[M], zmy, f[N] ;
int ban[N] ;
struct E {
int to, next, w ;
} e[N] ;
map<pi, int> S ;
struct node {
int x, y, z ;
};
node ST[15] ; int num ;
int fd(int x) {
return (fa[x] == x) ? fa[x] : fa[x] = fd(fa[x]) ;
}
void add(int x, int y, int z) {
e[++ cnt] = (E){ y, head[x], z }, head[x] = cnt,
e[++ cnt] = (E){ x, head[y], z }, head[y] = cnt ;
}
void merge(int x, int y, int zz) {
int u = fd(x), v = fd(y) ;
fa[u] = v, add(x, y, zz) ;
}
int dfn[N], color ;
void dfs(int x, int ff) {
zk[x] = 1 ;
Next( i, x ) {
int v = e[i].to ; if(v == ff) continue ;
if(ban[i]) continue ;
dfs(v, x) ;
dp[x][0] += max(dp[v][1], dp[v][0]) ;
dp[x][1] += max(dp[v][1] - e[i].w, dp[v][0]) ;
}
}
void Dfs(int x, int ff) {
dfn[x] = ++ color ;
if(x == ff) rt[x] = 1 ;
Next( i, x ) {
int v = e[i].to ; if(v == ff) continue ;
if( !dfn[v] ) Dfs( v, x ), g[x] |= g[v] ;
else if(dfn[v] < dfn[x])
ST[++ num] = (node){v, x, e[i].w}, ban[i] = 1, ban[i ^ 1] = 1, g[x] = 1 ;
}
}
int h[N], qls, cc[100], ttop ;
int root[N], fgo ;
signed main()
{
int xx, yy, zz ; cnt = 1 ;
n = gi(), m = gi(), xx = gi(), yy = gi(), A[0] = gi(), zz = gi() ;
rep( i, 1, n ) A[i] = (A[i - 1] * 101 + 137) % P ;
rep( i, 1, n ) fa[i] = i ;
rep( i, 1, m ) {
xx = (xx * 101 + 137) % P, yy = (yy * 101 + 137) % P,
zz = (zz * 101 + 137) % P ;
int x = xx % n + 1, y = yy % n + 1 ;
if(!S[mp(x, y)] && (x != y))
S[mp(x, y)] = S[mp(y, x)] = 1, merge(x, y, zz) ;
}
rep( i, 1, n ) if(!dfn[i]) Dfs(i, i) ;
for(re int i = 1; i <= num; ++ i)
st[++ top] = ST[i].x, st[++ top] = ST[i].y ;
sort(st + 1, st + top + 1) ;
rep( i, 1, top ) if(st[i] != st[i - 1]) c[++ zmy] = st[i] ;
int limit = (1 << zmy) - 1 ;
rep( i, 1, zmy ) f[c[i]] = 1 ;
int SA = 0 ;
rep( i, 1, n ) dp[i][0] = 0, dp[i][1] = A[i] ;
rep( i, 1, n ) if(rt[i] && (!g[i])) dfs(i, i), SA += max(dp[i][0], dp[i][1]) ;
rep( i, 1, n ) if(!zk[i]) h[++ qls] = i ;
rep( i, 1, n ) if(!zk[i] && rt[i]) root[++ fgo] = i ;
limit = (1 << num) - 1 ;
for(re int AC = 0; AC <= limit; ++ AC) {
int fSA = SA ;
rep( j, 1, zmy ) zt[c[j]] = 0 ;
for(re int j = 1; j <= num; ++ j) {
if(AC & (1 << (j - 1)))
fSA -= ST[j].z, zt[ST[j].x] = 1, zt[ST[j].y] = 1 ;
}
int lim = (AC ^ limit) ;
for(re int T = lim; ; T = (T - 1) & lim) {
rep( i, 1, qls ) zk[h[i]] = 0, dp[h[i]][1] = A[h[i]], dp[h[i]][0] = 0 ;
rep( j, 1, zmy ) if(zt[h[j]]) dp[h[j]][0] = -inf ;
rep( j, 1, num ) {
if(!((1 << (j - 1)) & lim)) continue ;
if((1 << (j - 1)) & T)
dp[ST[j].x][0] = -inf, dp[ST[j].y][1] = -inf ;
else
dp[ST[j].x][1] = -inf ;
}
int ans = fSA ;
rep( i, 1, fgo ) dfs(root[i], root[i]), ans += max( dp[root[i]][0], dp[root[i]][1] ) ;
Ans = max(Ans, ans) ;
if(!T) break ;
}
}
cout << Ans << endl ;
return 0 ;
}