题解 P3629 【[APIO2010]巡逻】
分析
luogu需要一篇vector题解
好吧我承认我代码写得有些冗长
k=1时,求树的直径长度记为L1,输出2(n-1)-L1+1;
k=2时,将k=1时的直径经过的边的权值记为-1,再求一遍树的直径记为L2,输出2n-L1-L2。
Code
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int x,y;
};
int n,k,vis[200010],fa[200010],Dis[200010],X,XX,f[200010],ans=-0x7FFFFFFF;
int ip1,ip2;
vector<int>a[200010];
int Get_len()
{
int res=0;
queue<Node>q;
q.push(Node{1,0});
memset(vis,0,sizeof(vis));
vis[1]=1;
while(!q.empty())
{
Node t=q.front();
q.pop();
for(int i=0;i<a[t.x].size();i++)
{
if(!vis[a[t.x][i]])
{
vis[a[t.x][i]]=1;
if(res<t.y+1)
{
res=t.y+1;
X=a[t.x][i];
}
q.push(Node{a[t.x][i],t.y+1});
}
}
}
memset(vis,0,sizeof(vis));
q.push(Node{X,0});
vis[X]=1;
while(!q.empty())
{
Node t=q.front();
q.pop();
for(int i=0;i<a[t.x].size();i++)
{
if(!vis[a[t.x][i]])
{
vis[a[t.x][i]]=1;
fa[a[t.x][i]]=t.x;
if(res<t.y+1)
{
res=t.y+1;
XX=a[t.x][i];
}
q.push(Node{a[t.x][i],t.y+1});
}
}
}
return res;
}
int Get_len2(int u,int FA)
{
for(int i=0;i<a[u].size();i++)
{
int v=a[u][i];
if(v==FA)
continue;
Get_len2(v,u);
int temp=1;
if(Dis[u]&&Dis[v])
temp=-1;
ans=max(ans,f[u]+f[v]+temp);
f[u]=max(f[u],f[v]+temp);
}
}
int find(int x)
{
if(fa[x]!=X)
{
int N=find(fa[x]);
Dis[N]=-1;
Dis[x]=-1;
}
return x;
}
void bfs1()
{
int ans=2*(n-1)-Get_len()+1;
cout<<ans;
return;
}
void bfs2()
{
int L1=Get_len();
find(XX);
Dis[X]=-1;
int L2=Get_len2(1,0);
cout<<2*n-L1-ans;
return;
}
int main()
{
cin>>n>>k;
for(int i=1;i<n;i++)
{
cin>>ip1>>ip2;
a[ip1].push_back(ip2);
a[ip2].push_back(ip1);
}
if(k==1)
{
bfs1();
}
if(k==2)
{
bfs2();
}
}
Orz