题解 P4381 【[IOI2008]Island】

luogu

分析

其实就是一个基环树森林,求每棵树的直径之和
用的\(vector\),常数巨大

艰辛而曲折的卡常之路

AC
T1.PNG
T2.PNG

Code

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define re register int
using namespace std;
inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9')
    {
        last=ch;ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans=(ans<<3)+(ans<<1);
        ans+=ch-'0';ch=getchar();
    }
    return last=='-'?-ans:ans;
}
inline long long Max(long long a,long long b)
{
	return a>b?a:b;
}
struct edge
{
	int to;
	long long dis;
	int F;
	edge(int tt,long long dd,int FF):to(tt),dis(dd),F(FF){}
};
long long dp[2000010],s[1000010],d[1000010],ANS,ans,ans2,ans3;
int n,ip1,ip2,st,cnt,CNT,vis[1000010],V[1000010],r[1000010];
vector<edge>a[1000010];
deque<int>q;
inline void Get_len(int now)
{
	vis[now]=1;
	for(re i=0;i<a[now].size();++i)
	{
	    register edge T=a[now][i];
		if(vis[T.to])
		{
			continue;
		}
		Get_len(T.to);
		ANS=max(ANS,d[now]+d[T.to]+T.dis);
		d[now]=max(d[now],d[T.to]+T.dis);
	}
}
inline int DFS(int now,int las)
{
	if(V[now]==1)
	{
		V[now]=2;
		r[++cnt]=now;
		vis[now]=1;
		return 1;
	}
	V[now]=1;
	for(re i=0;i<a[now].size();++i)
	{
	    register edge T=a[now][i];
		if(las!=T.F&&DFS(T.to,T.F))
		{
			if(V[now]!=2)
			{
				r[++cnt]=now;
				vis[now]=1;
				s[cnt]=s[cnt-1]+T.dis;
			}
			else
			{
				s[st-1]=s[st]-T.dis;
                return 0;
			}
			return 1;
		}
	}
	return 0;
}
inline long long BFS(int root)
{
	st=cnt+1,ans2=0,ans3=0;
	DFS(root,0);
	for(re i=st;i<=cnt;++i)
	{
		ANS=0;
		Get_len(r[i]);
		ans2=Max(ans2,ANS);
		dp[i+cnt-st+1]=dp[i]=d[r[i]];
        s[i+cnt-st+1]=s[i+cnt-st]+s[i]-s[i-1];
	}
	while(!q.empty())
	    q.pop_back();
    for(re i=st;i<=2*cnt-st+1;++i)
    {
        while(!q.empty()&&q.front()<=i-cnt+st-1)
            q.pop_front();
        if(!q.empty()) 
            ans3=Max(ans3,dp[i]+dp[q.front()]+s[i]-s[q.front()]);
        while(!q.empty()&&dp[q.back()]-s[q.back()]<=dp[i]-s[i])
            q.pop_back();
        q.push_back(i);
    }
    return Max(ans2,ans3);
}
int main()
{
	n=read();
	for(re i=1;i<=n;++i)
	{
		ip1=read();
		ip2=read();
		a[i].push_back(edge(ip1,ip2,++CNT));
		a[ip1].push_back(edge(i,ip2,CNT));
	}
	for(re i=1;i<=n;++i)
	{
		if(!vis[i])
		{
			ans+=BFS(i);
		}
	}
	printf("%lld",ans);
}
posted @ 2019-08-11 09:30  G_A_TS  阅读(404)  评论(0编辑  收藏  举报