Tree
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3534
题意:
有一棵树,问树上的最长路径以及最长路径的数量。
题解:
比较简单但是有点麻烦的一个题。设两个数组:
dp[i][0]代表以 i 为根节点的子树上的最长路径(i 点可以是端点也可以是中间点),dp[i][1]则代表该路径的数量
dis[i][0]代表以 i 为根节点的子树上的单程最长路径(i 点只能是端点而不可以是中间点),dis[i][1]则代表该路径的数量
那么问题就很简单了,dp[i]将可能由两种方式得到,①是由dp[child[i]]得到,②是max(dis[child[i]]+距离(i,child[i]))
①直接枚举环找最大的dp[child[i]][0]即可
②记录dis[child][0]的最大值和次大值以及它们的数量,最后做简单处理即可
经验证题目中的N不会大于1W,答案不会超过int32,且边权均大于0
代码
#include<stdio.h> #include<string.h> #include<vector> using namespace std; const int N=10005; int mmax(int x,int y) { return x>y?x:y; } struct node { int to,cost; node(int x=0,int y=0) { to=x,cost=y; } }; vector<node>q[N]; bool mark[N]; int dp[N][2],dis[N][2]; void Dfs_TreeDp(int id) { mark[id]=true; int mdis=-1,sdis=-1,mnum=0,snum=0,ss,mm; for(int i=0;i<q[id].size();++i) { int v=q[id][i].to; int w=q[id][i].cost; if(mark[v])continue; Dfs_TreeDp(v); if(dp[v][0]>dp[id][0]) { dp[id][0]=dp[v][0]; dp[id][1]=dp[v][1]; } else if(dp[v][0]==dp[id][0]) dp[id][1]+=dp[v][1]; if(dis[v][0]+w>mdis) { sdis=mdis,snum=mnum,snum=ss; mdis=dis[v][0]+w,mnum=1; mm=0,ss=dis[v][1]; } else if(dis[v][0]+w==mdis) mnum++,mm=mm+ss*dis[v][1],ss+=dis[v][1]; else if(dis[v][0]+w>sdis) { sdis=dis[v][0]+w; snum=dis[v][1]; } else if(dis[v][0]+w==sdis) snum+=dis[v][1]; } if(mdis!=-1) { dis[id][0]=mdis,dis[id][1]=ss; if(mnum>1) { if(mdis*2>dp[id][0]) { dp[id][0]=mdis*2; dp[id][1]=mm; } else if(mdis*2==dp[id][0]) { dp[id][0]=mdis*2; dp[id][1]+=mm; } } else if(sdis!=-1) { if(mdis+sdis>dp[id][0]) { dp[id][0]=mdis+sdis; dp[id][1]=snum*ss; } else if(mdis+sdis==dp[id][0]) { dp[id][0]=mdis+sdis; dp[id][1]+=snum*ss; } } else { if(mdis>dp[id][0]) { dp[id][0]=mdis; dp[id][1]=ss; } else if(mdis==dp[id][0]) { dp[id][0]=mdis; dp[id][1]+=ss; } } } if(dp[id][0]==0) { dp[id][1]=1; dis[id][1]=1; } } void solve() { int n,a,b,c; while(~scanf("%d",&n)) { memset(dp,0,sizeof(dp)); memset(dis,0,sizeof(dis)); for(int i=1;i<=n;++i) q[i].clear(); memset(mark,false,sizeof(mark)); if(n>10000)while(1); for(int i=1;i<n;++i) { scanf("%d%d%d",&a,&b,&c); if(c<=0||c*n>1000000000)while(1); q[a].push_back(node(b,c)); q[b].push_back(node(a,c)); } Dfs_TreeDp(1); printf("%d %d ",dp[1][0],dp[1][1]); } } int main() { solve(); return 0; }