世界「theworld」

前言

随机化不适合我。

题目

随机给 \(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;
}
posted @ 2021-11-17 16:13  皮皮刘  阅读(283)  评论(0编辑  收藏  举报