[IOI2008] Island

  • 基环树的直径
  • 两种情况:不经过环和经过环
  • 找环方法:深度优先遍历+限制回溯
  • 【注】较为简便的方法是记录一条边是否被访问过,但由于本题卡时卡空间,为了节省掉代替成对变换的vector数组,代码中只能将其替换为复杂的逻辑判断
  • 归并环上顺、逆时针两种情况:断环为链再复制一倍
  • 用deque实现单调队列
  • 给环上的每个节点打上特定标记,既能实现对基环树森林的枚举,又能得到每个环上的所有节点
  • 分部调试
  • 尽可能利用已有变量的编程原则
点击查看代码
#include <bits/stdc++.h>
using namespace std;
vector<int>a[1000005];
vector<int>c[1000005];
vector<int>z[500005];
vector<int>w[500005];
long long sw[1000005];
int m,g;
long long ans,d[1000005];
int h[1000005],r[1000005];
bool v[1000005];
deque<int>q;
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
int dfs(int n1,int fa,int va)
{
	bool f=false,b=false;
	v[n1]=true;
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=fa&&h[a[n1][i]]==0||a[n1][i]==fa&&r[n1]==a[n1][i]&&r[a[n1][i]]==n1&&(va!=c[n1][i]||b==true))
		{
			if(v[a[n1][i]]==false)
			{
				int tmp=dfs(a[n1][i],n1,c[n1][i]);
				if(tmp>0)
				{
					if(h[n1]==tmp)
					{
						f=true;
					}
					h[n1]=tmp;
					z[h[n1]].push_back(n1);
					w[h[n1]].push_back(c[n1][i]);
				}
			}
			else
			{
				m++;
				h[n1]=m;
				z[m].push_back(n1);
				w[m].push_back(c[n1][i]);
				h[a[n1][i]]=m;
			}
		}
		if(a[n1][i]==fa&&r[n1]==a[n1][i]&&r[a[n1][i]]==n1&&va==c[n1][i])
		{
			b=true;
		}
	}
	if(f==true)
	{
		return 0;
	}
	return h[n1];
}
void dp(int n1,int fa)
{
	for(int i=0;i<a[n1].size();i++)
	{
		if(h[a[n1][i]]==0&&a[n1][i]!=fa)
		{
			dp(a[n1][i],n1);
			ans=max(ans,d[n1]+d[a[n1][i]]+c[n1][i]);
			d[n1]=max(d[n1],d[a[n1][i]]+c[n1][i]);
		}
	}
}
int main()
{
//	freopen("island9.in","r",stdin);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int v=read1();
		int w=read1();
		a[i].push_back(v);
		a[v].push_back(i);
		c[i].push_back(w);
		c[v].push_back(w);
		r[i]=v;
	}
	for(int i=1;i<=n;i++)
	{
		if(!v[i])
		{
			int tmp=dfs(i,0,0);
		}
	}
	/*
	cout<<m<<endl;
	for(int i=1;i<=m;i++)
	{
		for(int j=0;j<z[i].size();j++)
		{
			cout<<z[i][j]<<' ';
		}
		cout<<endl;
		for(int j=0;j<w[i].size();j++)
		{
			cout<<w[i][j]<<' ';
		}
		cout<<endl;
	}
	*/
	long long sum=0;
	for(int i=1;i<=m;i++)
	{
		ans=0;
		for(int j=0;j<z[i].size();j++)
		{
			dp(z[i][j],0);
		}
		q.push_back(0);
		g=z[i].size();
		long long s=w[i][0];
		int cnt=0;
		sw[0]=s;
		for(int j=1;j<2*g;j++)
		{
			s=s+w[i][j%g];
			cnt++;
			sw[cnt]=s;
			int m1=q.front();
			if(m1==j-g)
			{
				q.pop_front();
				m1=q.front();
			}
			int u=z[i][m1%g];
			long long cur=sw[j]-sw[m1];
			int n1=z[i][j%g];
			ans=max(ans,d[u]+cur+d[n1]);
			while(!q.empty())
			{
				int m1=q.back();
				int u=z[i][m1%g];
				long long cur=sw[j]-sw[m1];
				if(d[n1]>=d[u]+cur)
				{
					q.pop_back();
				}
				else
				{
					break;
				}
			}
			q.push_back(j);
		}
		q.clear();
		sum+=ans;
	}
	cout<<sum<<endl;
	return 0;
}
/*
7
3 8
7 2
4 2
1 4
1 9
3 4
2 2
*/
posted @ 2024-01-21 17:13  D06  阅读(2)  评论(0编辑  收藏  举报