[NOI2003]逃学的小孩

算法:最短路+树的直径

难度:NOIP

注意:多年OI一场空,不开long long见祖宗!         如果不开long long,应该会被卡到60分!

注意:dfs找树的直径时,传的参数“d”也要开long long哦!!!

  

首先,因为无论如何答案都会包括A到B的dis,所以我们先用2遍dfs找到dis(A->B)的最大值(即:树的直径);

然后我们来考虑答案的另一部分:C到A/B的最大值,既然我们已经找到了树的直径的两个端点u,v,我们只需以u,v跑两遍SPFA,找到maxn,累加到ans身上即可。

伪代码:

maxn=max(maxn,1ll*min(dis[i],diss[i]));

代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ll long long
#define N 200005
using namespace std;
struct node
{
	int next;
	int to;
	int val;
}edge[N<<1];
int head[N],vis[N];
ll dis[N];
int cnt=1;
void init()
{
	memset(head,-1,sizeof(head));
	cnt=1;
}
void add(int u,int v,int w)
{
	edge[cnt].next=head[u];
	edge[cnt].to=v;
	edge[cnt].val=w;
	head[u]=cnt++;
}
void spfa(int rt)
{
	memset(dis,0x3f3f3f3f,sizeof(dis));
	dequeQ;
	vis[rt]=1;
	dis[rt]=0;
	Q.push_front(rt);
	while(!Q.empty())
	{
		int u=Q.front();
		Q.pop_front();
		for(int i = head[u];i != -1;i = edge[i].next)
		{
			int to=edge[i].to;
			if(dis[to]>dis[u]+edge[i].val)
			{
				dis[to]=dis[u]+edge[i].val;
				if(!vis[to])
				{
					vis[to]=1;
					if(!Q.empty()&&dis[to]Q;
	vis[rt]=1;
	diss[rt]=0;
	Q.push_front(rt);
	while(!Q.empty())
	{
		int u=Q.front();
		Q.pop_front();
		for(int i = head[u];i != -1;i = edge[i].next)
		{
			int to=edge[i].to;
			if(diss[to]>diss[u]+edge[i].val)
			{
				diss[to]=diss[u]+edge[i].val;
				if(!vis[to])
				{
					vis[to]=1;
					if(!Q.empty()&&diss[to]ans)
			{
				ans=dis[to];
				chan=to;
			}
			dfs(to,dis[to]);
		}
	}
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	init();
	for(int i = 1;i <= m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	viss[1]=1;
	dfs(1,0);
	va1=chan;
	memset(viss,0,sizeof(viss));
	viss[chan]=1;
	dfs(chan,0);
	va2=chan;
	if(va2==va1) va2=1;
	spfa(va1);
	ll maxn=0;
	spfaa(va2);
	for(int i = 1;i <= n;i++)
	{
		if(i==va1||va2==i) continue;
		if(diss[i]!=0x3f3f3f3f&&dis[i]!=0x3f3f3f3f) maxn=max(maxn,1ll*min(dis[i],diss[i]));
	}
	ans+=maxn;
	printf("%lld\n",ans);
	return 0;
} 

 

你可能感兴趣的:(树上问题(二)树的直径)