Highway Accepted : 33 Submit : 137 Time Limit : 4000 MS Memory Limit : 65536 KB Highway In ICPCCamp there were n towns conveniently numbered with 1,2,…,n connected with (n−1) roads. The i-th road connecting towns ai and bi has length ci. It is guaranteed that any two cities reach each other using only roads. Bobo would like to build (n−1) highways so that any two towns reach each using only highways. Building a highway between towns x and y costs him δ(x,y) cents, where δ(x,y) is the length of the shortest path between towns x and y using roads. As Bobo is rich, he would like to find the most expensive way to build the (n−1) highways. Input The input contains zero or more test cases and is terminated by end-of-file. For each test case: The first line contains an integer n. The i-th of the following (n−1) lines contains three integers ai, bi and ci. 1≤n≤105 1≤ai,bi≤n 1≤ci≤108 The number of test cases does not exceed 10. Output For each test case, output an integer which denotes the result. Sample Input 5 1 2 2 1 3 1 2 4 2 3 5 1 5 1 2 2 1 4 1 3 4 1 4 5 2 Sample Output 19 15 SourceXTU OnlineJudge
题目大意:
给出一棵无根树,给出n-1条边和权值,然后让你求重新选择n-1条边使其联通并且权和最大
题目思路: 这道题就是让你求对于i点,距离这个点最远的店,我们容易想到用dp写,但是这样明显有一个问题,就是会不会有重复的,还需要标记一下,有点麻烦,但是
其实我们不用担心这个,接下来我们引入树的直径的概念,并给出一些推论,树的直径是指树上权值和最大的路径(最简单路径,即每一个点只经过一次),存在结论:对于树上的任意一个一个节点,距离这个节点最远的距离一定是直径的两个端点,给出证明:假设当前点为u,直径端点为s,t,第一种情况:u在直径上,那么显然终点在端点上,我们用反证法证明,假设终点不在端点上,设其为e,那么存在dis(u-e)大于dis(u-s) 即存在dis(u-e)+dis(u-t)>dis(u-s)+dis(u-s)=dis(u-t)矛盾
第二种情况:u不在直径上
第一种情况,当u的最长路与直径相交,设交点为x,此时存在,dis(u-x)+dis(x-e)>dis(u-x)+dis(x-s) 即dis(u-x)+dis(x-e)+dis(x+t)>dis(u-x)+dis(x-s)+dis(x-t) = dis(u-x) +dis(s-t)矛盾,
第二种情况:不想交,这种麻烦点懒得推了
说一下求端点的技巧,选取任意一点开始dfs,去到的权值和最大的即为端点之一,然后从这个端点开始出发去寻找另一个端点
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<map> #include<iostream> #include<sstream> #include<string> #define LL long long #define INF 0x3f3f3f3f using namespace std; const int maxn = 1e5+10; int head[maxn*2]; int erear; LL dS[maxn*2]; LL dT[maxn*2]; struct node { LL x,to,cost,next; }E[maxn*2]; int n; void __init__() { memset(head,-1,sizeof(head)); memset(dS,0,sizeof(dS)); memset(dT,0,sizeof(dT)); erear = 0; } void build(LL x,LL y ,LL cost) { E[erear].x = x; E[erear].to = y; E[erear].cost = cost; E[erear].next = head[x]; head[x] = erear++; } void dfs1(LL u,LL &S,LL f) { if(dS[u]>dS[S]) S = u; for(LL i = head[u];i!=-1;i = E[i].next) { LL to = E[i].to; if(to==f) continue; dS[to] = dS[u]+E[i].cost; dfs1(to,S,u); } } void dfs2(LL u,LL fa,LL d[]) { for(LL i = head[u];i != -1;i=E[i].next) { int to = E[i].to; if(to==fa) continue; d[to] = d[u] + E[i].cost; dfs2(to,u,d); } } int main() { while(~scanf("%d",&n)) { __init__(); for(int i = 0 ;i<n-1;i++) { LL x,y,cost; scanf("%lld%lld%lld",&x,&y,&cost); build(x,y,cost); build(y,x,cost); } LL S,T; S = 1; dfs1(1,S,-1); T = S; dS[S] = 0; dfs1(S,T,-1); dfs2(S,-1,dS); dfs2(T,-1,dT); LL ans = 0; for(int i = 1;i<=n;i++) { ans += max(dS[i],dT[i]); } cout<<ans-dS[T]<<endl; //cout<<"\\n"<<endl; } }
ccpc湘潭邀请赛 h-highway(树的直径)
最新推荐文章于 2022-12-29 11:19:29 发布