此题不错!(可惜考场没时间打了 )
两种做法哦~,有种简单但慢,有种快速但难想。。。
先讲简单的:
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
",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;
}