- 基环树的直径
- 两种情况:不经过环和经过环
- 找环方法:深度优先遍历+限制回溯
- 【注】较为简便的方法是记录一条边是否被访问过,但由于本题卡时卡空间,为了节省掉代替成对变换的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
*/