做题记录整理图论1 P3629 [APIO2010] 巡逻(2022/10/4)

P3629 [APIO2010] 巡逻

写一道题顶写三道题系列,
为了写这道题专门去学习了树的直径的两种求法,可以说是血赚了
https://www.luogu.com.cn/blog/lscsznmhw/solution-p3629
由于没学过类似题目,还是看了题解。。。

#include<bits/stdc++.h>
#define for1(i,a,b) for(ll i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;

struct node{
	int nex;
	int to;
	int w;
} a[500010];
int hd[100010],cnt;
int n,k;
int mx,ji,d1,d2,st,ed,fr[100010],dis[100010];
bool kg;
map<int,bool>ma;

void ru(int x,int y) 
{
	a[++cnt].to=y;
	a[cnt].nex=hd[x];
	a[cnt].w=1;
	hd[x]=cnt;
}

void dfs(int x,int fa,int we) 
{
	if(we>=mx)
	{
		mx=we;
		ji=x;
	}
	for(int i=hd[x];i;i=a[i].nex)
		if(a[i].to!=fa)
			dfs(a[i].to,x,we+a[i].w);
}

void dfs2(int now,int fa,int t) 
{
	if(kg)  return;
	for(int i=hd[now]; i; i=a[i].nex) 
	{
		if(kg)  return;
		if(a[i].to==fa)  continue;
		if(a[i].to==t) 
		{
			fr[now]=a[i].to;
			kg=1;
			return;
		}
		fr[now]=a[i].to;
		dfs2(a[i].to,now,t);
		if(kg)  return;
	}
}

void dfs3(int now,int fa)
 {
	for(int i=hd[now]; i; i=a[i].nex) 
	{
		if(a[i].to==fa)  continue;
		dfs3(a[i].to,now);
		d2=max(d2,dis[now]+dis[a[i].to]+a[i].w);
		dis[now]=max(dis[now],dis[a[i].to]+a[i].w);
	}
}

int main() 
{
    int x,y;
	cin>>n>>k;
	for1(i,1,n-1)
	{
		cin>>x>>y;
		ru(x,y);
		ru(y,x);
	}
	dfs(1,0,0);
	st=ji,mx=0;
	dfs(st,0,0);
	d1=mx,ed=ji;
	if(k==1) 
	{
		printf("%d",(2*(n-1)-d1+1));
		return 0;
	}
	dfs2(st,0,ed);
	ma[ed]=1,ma[st]=1;
	for(int i=st;i!=ed;i=fr[i]) ma[i]=1;
	for1(i,1,n)
		if(ma.count(i)==1)
			for(int j=hd[i];j;j=a[j].nex)
				if(ma.count(a[j].to)==1)
					a[j].w=-1;
	dfs3(1,0);
	printf("%d",2*n-d1-d2);
	return 0;
}
posted @ 2022-10-04 19:53  yyx525jia  阅读(21)  评论(0)    收藏  举报