80分wa求助
查看原帖
80分wa求助
32490
memory_frv楼主2021/11/15 21:31

对拍了好久也没找出错误来,球球啦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
inline ll read(){
	ll f=1,x=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return f*x;
}
struct edge{
	ll nxt,v;
	ll val;
}e[2500001];
ll n,tot=1,head[2000001],rd[2000001],d[2000001],q[2000001],cnt=0,father[2000001],hhead=0,tail=0;
ll ssum[2000001],dis[2000001];
bool vis[2000001],vis1[2000001],vis2[2000001];
pair<ll,ll> que[2000001];
inline ll getfather(ll x){
	if(father[x]==x) return x;
	return father[x]=getfather(father[x]);
}
inline void add(ll u,ll v,ll val){
	e[++tot].v=v,e[tot].val=val,e[tot].nxt=head[u],head[u]=tot;
	e[++tot].v=u,e[tot].val=val,e[tot].nxt=head[v],head[v]=tot;
}
inline ll dfs(ll now,ll fa,ll top){//求子树 
	ll d1=0,d2=0;
	for(ll i=head[now];i;i=e[i].nxt){
		ll to=e[i].v;
		if(to==fa||!vis[to]) continue;
		ll t=dfs(to,now,top)+e[i].val;
		if(t>d1){
			d2=d1,d1=t;
		}else if(t>d2) d2=t;
	}
	d[top]=max(d[top],d1+d2);
	return d1;
}
inline void dfs1(ll now,ll fa,ll top){//取出环 
	q[++cnt]=now;
	for(ll i=head[now];i;i=e[i].nxt){
		ll to=e[i].v;
		if(vis[to]||to==fa) continue;
		if(to==top){
			dis[cnt+1]=dis[cnt]+e[i].val;
			break;
		}
		dis[cnt+1]=dis[cnt]+e[i].val;
		dfs1(to,now,top);
		break;
	}
}
inline void dfs2(ll top){//求环上一个点的所有子树直径最大值 
	for(ll i=head[top];i;i=e[i].nxt){
		int to=e[i].v;
		if(!vis[to]) continue;
		d[top]=max(d[top],dfs(to,top,to)+e[i].val);
	}
}
int main(){
	freopen("3.in","r",stdin);
	n=read();
	for(ll i=1;i<=n;i++) father[i]=i,ssum[i]=1;
	
	for(ll i=1;i<=n;i++){
		
		ll v,val;
		v=read(),val=read();
	
		add(i,v,val);
		ll f1=getfather(i),f2=getfather(v);
		if(f1!=f2) father[f1]=f2,ssum[f2]+=ssum[f1];
		rd[i]++,rd[v]++;
	}
	queue<ll> qq;
	for(ll i=1;i<=n;i++){
		if(rd[i]==1){
			qq.push(i);
		}
	}
	
	while(!qq.empty()){//拓扑排序找环 
		ll u=qq.front();
		qq.pop();
		vis[u]=1;
		for(ll i=head[u];i;i=e[i].nxt){
			ll to=e[i].v;
			rd[to]--;
			if(rd[to]==1){
				qq.push(to);
			}
		}
	}
	for(ll i=1;i<=n;i++){
		if(!vis[i]){
			dfs2(i);
		}
	}
	ll sum=0;
	for(ll i=1;i<=n;i++){
		if(!vis[i]&&!vis1[getfather(i)]&&rd[i]>1){
			que[0]=que[1]=que[2]=make_pair(0,0);
			cnt=0;
			vis1[getfather(i)]=1;
			if(ssum[getfather(i)]==2){ //特判环大小为2的情况(应该没有问题) 
				ll al,temp;
				cnt=1;
				q[1]=i;
				for(ll j=head[i];j;j=e[j].nxt){
					ll to=e[j].v;
					if(!vis[to]){
						temp=to;
						al=j;
						q[2]=to,q[3]=i,q[4]=to;
						dis[cnt+1]=dis[cnt]+e[j].val;cnt++;
						break;
					}
				}
				for(ll j=head[temp];j;j=e[j].nxt){
					ll to=e[j].v;
					if(!vis[to]&&j!=(al^1)){
						dis[cnt+1]=dis[cnt]+e[j].val;
						break;
					}
				}
				dis[cnt+2]=dis[cnt+1]+dis[cnt]-dis[cnt-1];
			}else{
				dfs1(i,i,i);
				for(ll j=cnt+1;j<=2*cnt;j++){//把序列增长一倍 
					q[j]=q[j-cnt];
					if(j>cnt+1) dis[j]=dis[j-1]+dis[j-cnt]-dis[j-cnt-1];
				}	
			}
			hhead=tail=1;
			ll ans=0;
			for(ll j=1;j<=2*cnt;j++){//单调队列求答案 
				while(hhead<=tail&&que[hhead].second<=j-cnt) hhead++;
				ans=max(ans,d[q[j]]+dis[j]+que[hhead].first);
				ll temp=d[q[j]]-dis[j];
				while(hhead<=tail&&temp>que[tail].first) tail--;
				que[++tail]=make_pair(temp,j);
			}
			sum+=ans;
		}
	}
	cout<<sum;
	return 0;
}
2021/11/15 21:31
加载中...