1. 程式人生 > >【提高組NOIP2007】樹網的核

【提高組NOIP2007】樹網的核

此題不錯!(可惜考場沒時間打了
兩種做法哦~,有種簡單但慢,有種快速但難想。。。
先講簡單的:

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;    
}