【提高组NOIP2007】树网的核

版权声明:嘻嘻,要转的话请告知一声~ https://blog.csdn.net/Larry1118/article/details/85392608

此题不错!(可惜考场没时间打了
两种做法哦~,有种简单但慢,有种快速但难想。。。
先讲简单的:

Floyd+暴判

呵呵,标题好吓人啊。
但其实真的很简单,经过调查研究发现,F一定是在直径上,所以所求最小偏心距也一定是在F上(也就是不可能在不是直径的路径上)。
上标:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int d[301][301],n,s,ma=0,ans=300000;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int main()
{
	freopen("core.in","r",stdin);
	freopen("core.out","w",stdout);
	n=read(),s=read();
	memset(d,10,sizeof(d));
	for (int i=1;i<=n;i++) d[i][i]=0;
	for (int i=1,u,v;i<n;i++)
		u=read(),v=read(),d[u][v]=d[v][u]=read();
	for (int k=1;k<=n;k++)
		for (int i=1;i<=n;i++) if (d[i][k]<300000)
			for (int j=1;j<=n;j++) if (d[k][j]<300000)
					d[i][j]=d[j][i]=min(d[i][j],d[i][k]+d[k][j]);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
			if (d[i][j]<=s)
			{
				ma=0;
				for (int k=1;k<=n;k++)
					ma=max(ma,(d[i][k]+d[k][j]-d[i][j])>>1);
				ans=min(ans,ma);
			}
	printf("%d\n",ans);
	return 0;
}

“直径”大法

我们可以先找到一条直径上的一点,再找到直径上的一端的点,然后暴力枚举点以及能延伸到的最远的直径上的路径,然后再搞搞求求答案即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int v,fr,d;}e[601];
int ans=1e9,rt,d[601],n,m,s,tot=0,fa[601],tail[601];
bool bz[601];

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

void add(int u,int v,int w) {e[++tot]=(node){v,tail[u],w}; tail[u]=tot;}

void dfs(int x)
{
	for (int p=tail[x],v;p;p=e[p].fr)
		if ((v=e[p].v)!=fa[x] && !bz[v])
			fa[v]=x,d[v]=d[x]+e[p].d,dfs(v);
}

int main()
{
	freopen("core.in","r",stdin);
	freopen("core.out","w",stdout);
	n=read(),s=read();
	for (int i=1,u,v,w;i<n;i++)
		u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);
	rt=1;d[1]=0;fa[1]=0;dfs(1);
	for (int i=1;i<=n;i++) rt=d[i]>d[rt] ? i:rt;
	d[rt]=0;fa[rt]=0;dfs(rt);
	for (int i=1;i<=n;i++) rt=d[i]>d[rt] ? i:rt;
	for (int x=rt,j=rt;x;x=fa[x])
	{
		while (fa[j] && d[x]-d[fa[j]]<=s) j=fa[j];
		ans=min(ans,max(d[j],d[rt]-d[x]));bz[x]=1;
	}
	for (int i=rt;i;i=fa[i]) d[i]=0,dfs(i);
	for (int i=1;i<=n;i++) ans=max(ans,d[i]);
	printf("%d",ans);
	return 0;    
}

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/85392608