记录编号 442172 评测结果 AAAAAAAAAAA
题目名称 子集 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.031 s
提交时间 2017-08-26 12:21:37 内存使用 4.87 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,m,id,v[N],w[N],head[N],next[N];
bool incir[N];
void add(int f,int t){
	static int cnt=1;
	w[++cnt]=t;
	next[cnt]=head[f];
	head[f]=cnt;
}
int fa[N],up[N];
bool vis[N],use[N],cir[N];
void dfs(int x){
	vis[x]=1;
	for (int i=head[x];i;i=next[i])
	if (!use[i]){
		use[i]=use[i^1]=1;
		int v=w[i];
		if (v==fa[x]) continue;
		if (vis[v]){
			id++;
			add(id,v);add(v,id);
			cir[i]=cir[i^1]=1;
			for (int i=x;i!=v;i=fa[i]){//按顺序加边,以便后面dp使用
				add(id,i);add(i,id);
				cir[up[i]]=cir[up[i]^1]=1;
			}
		}
		else up[v]=i,fa[v]=x,dfs(v);
	}
}
int dp[N][2];//dp[i][j]表示以i为根的仙人掌中取/不取根的最大独立集
void solve(int x,int fa){
	if (x<=n){//圆点
		dp[x][1]=v[x];
		for (int i=head[x];i;i=next[i])
		if (!cir[i]&&w[i]!=fa){
			int v=w[i];
			solve(v,x);
			if (v<=n) dp[x][1]+=dp[v][0],dp[x][0]+=max(dp[v][0],dp[v][1]);
				else dp[x][1]+=dp[v][1],dp[x][0]+=dp[v][0];
		}
	}
	else{//方点
		for (int i=head[x];i;i=next[i])
			if (!cir[i]&&w[i]!=fa) solve(w[i],x);
		//从根开始,化环为链
		static int q[N],f[N][2];//f[i][j]表示前i个中选/不选最后一个的最大独立集
		int size=0;
		for (int i=head[x];i;i=next[i])
			if (!cir[i]&&w[i]!=fa) q[++size]=w[i];
		//求dp[x][1]
		f[1][0]=dp[q[1]][0];f[1][1]=-1e9;
		for (int i=2;i<=size;i++)
			f[i][1]=f[i-1][0]+dp[q[i]][1],f[i][0]=max(f[i-1][0],f[i-1][1])+dp[q[i]][0];
		dp[x][1]=f[size][0];
		//求dp[x][0]
		f[1][0]=dp[q[1]][0];f[1][1]=dp[q[1]][1];
		for (int i=2;i<=size;i++)
			f[i][1]=f[i-1][0]+dp[q[i]][1],f[i][0]=max(f[i-1][0],f[i-1][1])+dp[q[i]][0];
		dp[x][0]=max(f[size][0],f[size][1]);
	}
}
int main()
{
	freopen("subseta.in","r",stdin);
	freopen("subseta.out","w",stdout);
	scanf("%d",&n);id=n;
	for (int i=1;i<=n;i++) scanf("%d",&v[i]);
	scanf("%d",&m);
	for (int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	int ans=0;
	for (int i=1;i<=n;i++)
		if (!vis[i]) dfs(i),solve(i,0),ans+=max(dp[i][0],dp[i][1]);
	printf("%d\n",ans);
	return 0;
}