基环树直径WA40 求大佬帮调错
查看原帖
基环树直径WA40 求大佬帮调错
147670
金珂拉楼主2021/7/12 14:05

思路没用题解里的思路,是先求去掉环上的其中一条边后的整棵树的直径,再求必须经过其中一条边的情况下的最长路径(这里用了类似题解的方法)

请问是思路错了还是代码有锅

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int u,v,nt;
	long long w;
};
node e[3000020];
int h[3000003],tot,opp[3000003];
void add(int x,int y,long long z)
{
    tot++;
    e[tot].u=x;
    e[tot].v=y;
    e[tot].w=z;
    e[tot].nt=h[x];
    h[x]=tot;
}
long long dis[3000003],f[3000003];
int fa[3000003],tag[3000003],cnt,top,a[3000003];
long long ans;
bool vis2[3000003],vis[3000003];
void count(int x,int pr){
	vis[x]=1;
	for(int i=h[x];i;i=e[i].nt)
	if(!vis[e[i].v]){
	fa[e[i].v]=x;
	count(e[i].v,i);
	f[x]=max(f[x],dis[x]+dis[e[i].v]+e[i].w);
	dis[x]=max(dis[x],dis[e[i].v]+e[i].w);
	ans=max(ans,f[x]);
	}
	else 
	if(opp[i]!=pr&&!top) {
	tag[cnt]=i;
	a[++top]=x;
	vis2[x]=1;
	while(a[top]!=e[i].v){
	a[top+1]=fa[a[top]];
	vis2[a[top+1]]=1;
	top++;
	}
	}
}
long long dis2[3000003],sum[3000003],maxn2[3000003];
void dfs2(int x){
	vis2[x]=1;
	for(int i=h[x];i;i=e[i].nt)
	if(!vis2[e[i].v]){
	dfs2(e[i].v);
	dis2[x]=max(dis2[e[i].v]+e[i].w,dis2[x]);
	}
} 
void count2(){
	sum[1]=0;
	maxn2[0]=-(1ll<<62);
	for(int i=1;i<=top;i++){
	sum[i+1]=sum[i]+dis[a[i+1]]-dis[a[i]];
	dfs2(a[i]);
	maxn2[i]=max(maxn2[i-1],sum[i]+dis2[a[i]]);
	}
	for(int i=top;i>=2;i--){
	ans=max(ans,maxn2[i-1]+dis2[a[i]]+e[tag[cnt]].w+sum[top]-sum[i]);
	}
}
int n,k;
long long res=0;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
	int y;
	long long z;
	scanf("%d%lld",&y,&z);
	add(i,y,z);
	opp[tot]=tot+1;
	add(y,i,z);
	opp[tot]=tot-1;
	}
	for(int i=1;i<=n;i++){
	if(!vis[i]){
	ans=0;
	cnt++;
	top=0;
	count(i,0);
	count2();
	res+=ans;
	}
	}
	printf("%lld",res);
}
2021/7/12 14:05
加载中...