hack数据WA on #2 #4求助
查看原帖
hack数据WA on #2 #4求助
677939
westernhan楼主2024/3/9 15:48

思路是先对连接环的每条子树做树形DP再对环做一次环DP。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define max(a,b) ((a)>(b)?(a):(b))
int n,f[100005][2],x,y,cnt,head[100005],ru[100005],que[100005],c[100005],tot,p[100005][2],ans;
double k;
typedef struct _edge
{
	int to,nxt;
}edge;
edge e[200005];
void addedge(int w,int h)
{
	cnt++;
	e[cnt].to=h;
	e[cnt].nxt=head[w];
	head[w]=cnt;
}
void dfs(int w,int fa)
{
	for (int i=head[w];i;i=e[i].nxt)
	{
		int v=e[i].to;
		if (v==fa||ru[v]==2) continue;
		dfs(v,w);
		f[w][0]+=max(f[v][0],f[v][1]);
		f[w][1]+=f[v][0];
	}
}
void topo(void)
{
	int h=1,t=0;
	for (int i=1;i<=n;i++)
		if (ru[i]==1) que[++t]=i;
	while (h<=t)
	{
		int u=que[h++];
		for (int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			ru[v]--;
			if (ru[v]==1) que[++t]=v;
		}
	}
	for (int i=1;i<=n;i++)
		if (ru[i]==2)
		{
			dfs(i,0);
			c[++tot]=i;
		}
}
int main(void)
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",f[i]+1);
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);x++;y++;
		ru[x]++;ru[y]++;
		addedge(x,y);addedge(y,x);
	}
	scanf("%lf",&k);
	topo();
	//for (int i=1;i<=n;i++) printf("%d %d\n",f[i][0],f[i][1]);
	memset(p,-0x3f,sizeof(p));
	p[1][0]=f[c[1]][0];
	for (int i=2;i<=tot;i++)
	{
		p[i][0]=max(p[i-1][0],p[i-1][1])+f[c[i]][0];
		p[i][1]=p[i-1][0]+f[c[i]][1];
		//printf("%d:%d\n",p[i][0],p[i][1]);
	}
	ans=max(ans,p[tot][0]);
	ans=max(ans,p[tot][1]);
	memset(p,-0x3f,sizeof(p));
	p[1][1]=f[c[1]][1];
	for (int i=2;i<=tot;i++)
	{
		p[i][0]=max(p[i-1][0],p[i-1][1])+f[c[i]][0];
		p[i][1]=p[i-1][0]+f[c[i]][1];
		//printf("%du%d\n",p[i][0],p[i][1]);
	}
	ans=max(ans,p[tot][0]);
	printf("%.1lf\n",k*(double)ans);
	return 0;
}

2024/3/9 15:48
加载中...