当前位置: 代码迷 >> 综合 >> ural 1056 Computer Net(树形DP)需要用到两遍dfs
  详细解决方案

ural 1056 Computer Net(树形DP)需要用到两遍dfs

热度:48   发布时间:2024-01-13 20:36:46.0

1、http://acm.timus.ru/problem.aspx?space=1&num=1056

2、题目大意;

有n台计算机相连,已知1是根节点,现在要求的是谁是这个网络中的中心?

就是求每个点到其他点的最远距离中的最小距离的点

我们首先得求出每个点到其他点的最大距离来,然后找出这里边最小的距离对应的点是哪个

我们可以用两遍dfs求出来,

第一遍dfs,更新出每个结点的最远距离

第二次dfs,更新子节点是否可以通过自己的父节点可以到达更远的点

用dp[i][1]表示i点的最大值,dp[i][0]表示i点的次大值

最后只需要将dp[i][1]中最小的那个i值输出即可,可能不止一个

3、AC代码:

#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10005
#define INF 0x7fffffff
vector<int> adj[N*2];
int visit[N];
int dp[N][2],ans;
//dp[i][1]记录i点的最大值,dp[i][0]记录i点的次大值
void dfs1(int u)
{visit[u]=1;for(int i=0; i<adj[u].size(); i++){int v=adj[u][i];if(visit[v]==0){dfs1(v);if(dp[v][1]+1>dp[u][1]){dp[u][0]=dp[u][1];dp[u][1]=dp[v][1]+1;}else if(dp[v][1]+1>dp[u][0]){dp[u][0]=dp[v][1]+1;}}}
}
void dfs2(int u)
{visit[u]=1;for(int i=0; i<adj[u].size(); i++){int v=adj[u][i];//更新子节点的最大值和次大值if(visit[v]==0){int tmp;//如果v在父节点的最大链上,tmp=次大值+1if(dp[u][1]==dp[v][1]+1)tmp=dp[u][0]+1;elsetmp=dp[u][1]+1;if(tmp>dp[v][1]){dp[v][0]=dp[v][1];dp[v][1]=tmp;}else if(tmp>dp[v][0]){dp[v][0]=tmp;}if(ans>dp[v][1])ans=dp[v][1];dfs2(v);}}
}
int main()
{int n,a;scanf("%d",&n);for(int i=2; i<=n; i++){scanf("%d",&a);adj[i].push_back(a);adj[a].push_back(i);}ans=INF;memset(visit,0,sizeof(visit));dfs1(1);memset(visit,0,sizeof(visit));dfs2(1);for(int i=1;i<=n;i++){if(dp[i][1]==ans)printf("%d ",i);}printf("\n");return 0;
}


 

  相关解决方案