前言
随机化不适合我。
题目
随机给 \(n\) 个点 \(m\) 条边,点有正权,边有负权,求权值最大的诱导子图的权值。
\(1\le n\le 10^5;0\le m\le \frac{n}{2}.\)
讲解
首先如果不是随机的,那么这个问题和最大独立集差不多,直接嗝屁。
但是它是随机的,而且边很少,图很稀疏,所以环就特别少,直接跑出dfs树然后枚举返祖边上的点选不选,树形dp即可。
大样例甚至就是森林。
时间复杂度 \(O(n)\)?
代码
甚至只写树的部分都有45pts
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;
typedef long long LL;
const int MAXN = 200005;
const LL INF = 12345678910111ll;
const int p = 1e9+7;
const int q = 101;
const int b = 137;
map<pair<int,int>,int> me;
int n,m,x[MAXN],y[MAXN],a[MAXN],U[MAXN],V[MAXN],W[MAXN],d[MAXN];
LL Read()
{
LL x = 0,f = 1; char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10)+(c^48);c = getchar();}
return x * f;
}
TT void Put1(T x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}
int head[MAXN],tot;
struct edge
{
int v,w,nxt;
}e[MAXN<<1];
void Add_Edge(int u,int v,int w)
{
e[++tot] = edge{v,w,head[u]};
head[u] = tot;
}
void Add_Double_Edge(int u,int v,int w)
{
Add_Edge(u,v,w);
Add_Edge(v,u,w);
}
bool vis[MAXN];
int s[MAXN],tl,fs[MAXN],tt,ptot,val[MAXN];
pair<int,int> pp[MAXN];
void dfs1(int x,int fa)
{
vis[x] = 1; s[++tl] = x; d[x] = d[fa] + 1;
for(int i = head[x]; i ;i = e[i].nxt)
if(!vis[e[i].v]) dfs1(e[i].v,x);
else if(e[i].v != fa && d[e[i].v] < d[x]) fs[++tt] = x,fs[++tt] = e[i].v,pp[++ptot] = make_pair(x,e[i].v),val[ptot] = e[i].w;
}
LL dp[MAXN][2];
void dfs2(int x)
{
dp[x][1] += a[x];
for(int i = head[x],v; i ;i = e[i].nxt)
if(d[v = e[i].v] == d[x] + 1)
{
dfs2(v);
dp[x][0] += Max(dp[v][0],dp[v][1]);
dp[x][1] += Max(dp[v][0],dp[v][1]-e[i].w);
}
}
int main()
{
freopen("theworld.in","r",stdin);
freopen("theworld.out","w",stdout);
n = Read(); m = Read(); x[0] = Read(); y[0] = Read(); a[0] = Read(); W[0] = Read();
for(int i = 1;i <= n;++ i) a[i] = (1ll*q*a[i-1]+b)%p;
for(int i = 1;i <= m;++ i)
{
x[i] = (1ll*q*x[i-1]+b)%p;
y[i] = (1ll*q*y[i-1]+b)%p;
W[i] = (1ll*q*W[i-1]+b)%p;
U[i] = x[i]%n+1,V[i] = y[i]%n+1;
if((U[i]^V[i]) && !me[make_pair(U[i],V[i])])
me[make_pair(U[i],V[i])] = me[make_pair(V[i],U[i])] = 1,Add_Double_Edge(U[i],V[i],W[i]);
}
LL ans = 0;
for(int i = 1;i <= n;++ i)
{
if(vis[i]) continue;
ptot = tl = tt = 0;
dfs1(i,0);
if(tt)
{
LL MAX = 0;
sort(fs+1,fs+tt+1); tt = unique(fs+1,fs+tt+1)-fs-1;
for(int S = 0;S < (1<<tt);++ S)
{
for(int j = 1;j <= tl;++ j) dp[s[j]][0] = dp[s[j]][1] = 0;
for(int j = 0;j < tt;++ j)
if(S >> j & 1) dp[fs[j+1]][1] = INF,dp[fs[j+1]][0] = -INF;
else dp[fs[j+1]][1] = -INF,dp[fs[j+1]][0] = INF;
for(int j = 1;j <= ptot;++ j)
if(dp[pp[j].first][1] > 0 && dp[pp[j].second][1] > 0)
dp[pp[j].first][1] -= val[j];
dfs2(i); MAX = Max(MAX,Max(dp[i][0],dp[i][1]));
}
ans += MAX-INF*tt;
}
else dfs2(i),ans += Max(dp[i][0],dp[i][1]);
}
Put(ans,'\n');
return 0;
}