给你一棵树,找出两个叶子之间的最短距离。
第一种是个纯dfs+稍微的剪枝,从每一个叶子出发,dfs直到找到一个新的叶子,更新最短距离。781ms
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#define MAXN 10001
#define INF 2147483647
using namespace std;
int n;
vector<int>g[MAXN],w[MAXN];
int angel[MAXN];
int maxx;
bool vis[MAXN];
void dfs(int ori,int cur,int dis)
{
if(dis>=maxx) return ;
vis[cur]=true;
if(angel[cur]==1&&cur!=ori)
{
maxx=min(maxx,dis);
return ;
}
for(int i=0; i<(int)g[cur].size(); i++)
{
int t=g[cur][i];
if(!vis[t]&&w[cur][i]+dis<maxx)
dfs(ori,t,w[cur][i]+dis);
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0; i<=n; i++)
g[i].clear(),w[i].clear(),angel[i]=0;
maxx=INF;
for(int i=0; i<n-1; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
angel[a]++,angel[b]++;
g[a].push_back(b),w[a].push_back(c);
g[b].push_back(a),w[b].push_back(c);
}
for(int i=1; i<=n; i++)
if(angel[i]==1)
{
memset(vis,false,sizeof(vis));
dfs(i,i,0);
}
printf("%d\n",maxx);
}
return 0;
}
第二种是新接触的树形dp,从任意一个节点出发,dfs回溯,dp[cur][0]表示cur节点到叶子的最短距离,dp[cur][1]表示cur节点到叶子的次短距离。注意dp数组的初始化,(每一个叶子到叶子的最短距离是0)。PS.树形dp,它的原理和名字很像。dp[cur][0]=min{dp[cur][0],dp[u][0]+dis(u,cur)],因为父节点cur的dp值通过子节点来得出,所以通过回溯递归求解每一个节点的dp[][].
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#define MAXN 10010
#define INF 20000000
using namespace std;
vector<int>g[MAXN],w[MAXN];
int n,dp[MAXN][2],degree[MAXN];
bool vis[MAXN];
int maxx;
void dfs(int cur)
{
vis[cur]=true;
for(int i=0; i<(int)g[cur].size(); i++)
{
int t=g[cur][i];
if(!vis[t])
{
dfs(t);
if(w[cur][i]+dp[t][0]<dp[cur][0])
{
dp[cur][1]=dp[cur][0];
dp[cur][0]=w[cur][i]+dp[t][0];
}
else if(w[cur][i]+dp[t][0]<dp[cur][1])
dp[cur][1]=w[cur][i]+dp[t][0];
// printf("cur:%d %d %d\n",cur,dp[cur][0],dp[cur][1]);
}
}
maxx=min(maxx,dp[cur][0]+dp[cur][1]);
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0; i<=n; i++)
g[i].clear(),w[i].clear(),degree[i]=0;
for(int i=1; i<n; i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
degree[a]++,degree[b]++;
g[a].push_back(b),g[b].push_back(a);
w[a].push_back(c),w[b].push_back(c);
}
for(int i=1; i<=n; i++)
{
dp[i][0]=dp[i][1]=INF;
if(degree[i]==1)
dp[i][0]=0;
}
memset(vis,false,sizeof(vis));
maxx=INF;
dfs(1);
printf("%d\n",maxx);
}
return 0;
}