题目链接:
http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267
Description
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
大意:
题意很简单,给一个生成树,求这个基础上求最大生成树。
思路:
从任意一个点开始 DFS ,找到一个端点,这个端点是离这个点的最远点记为S,再从 S 开始 DFS ,找到离 S 最远的点 T,那么 S-T 就是这个树的直径。即最远的路。
易得所有点开始 DFS 最终必然都会到 S、T 中的某一点。记下他们到 S 和到 T 的距离,取 max 全部相加并减去多算一次的直径就是最终答案
- 从任一点 DFS 得到直径的一个端点 S
- 从 S 开始 DFS 得到直径的另一个端点 T
两次 DFS 得到直径 S-T
再来两次,起点设为 S、T 可以得到距离
在实际操作中,可以在步骤2的同时,即完成距离计算。
代码1 ,4个 DFS
#include <iostream>
#include <string>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
const ll MAXN =1e5+10;
ll head[MAXN],cnt=0;
struct Edge{
ll next,from,to,cost;
}E[MAXN*2];
ll Scan(){ //输入外挂
ll res=0,flag=0;
char ch;
if((ch=getchar())=='-'){
flag=1;
}else if((ch>='0' && ch<='9')){
res=ch-'0';
}else ;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch-'0');
return flag? -res:res;
}
void _build(ll from,ll to,ll cost){
E[cnt].from=from;
E[cnt].to=to;
E[cnt].cost=cost;
E[cnt].next=head[from]; //链式前向星
head[from]=cnt++;
}
void build(ll from,ll to,ll cost){
_build(to,from,cost);
_build(from,to,cost);
}
ll dS[MAXN*2],dT[MAXN*2];
void Init(){
mem(dS,0);
mem(dT,0);
mem(head,-1);
cnt=0;
}
void dfs1(ll u,ll &S,ll end){ //end为边界
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==end) continue; //防止往回找
dS[to]=dS[u]+E[i].cost;
dfs1(to,S,u);
}
}
void dfs2(ll u,ll *d,ll end){
for(ll i=head[u];i+1;i=E[i].next){
ll to=E[i].to;
if(to==end) continue;
d[to]=d[u]+E[i].cost;
dfs2(to,d,u);
}
}
int main(){
ll n;while(~scanf("%lld",&n)){
Init();
for(ll i=0;i<n-1;i++){
ll from,to,cost;
from=Scan();to=Scan();cost=Scan();
build(from,to,cost);
}
ll S=1,T=1;
dfs1(1,S,-1);
T=S;
dS[S]=0;
dfs1(S,T,-1);
dfs2(S,dS,-1);
dfs2(T,dT,-1);
ll ans=0;
for(ll i=1;i<=n;i++){
ans+=max(dS[i],dT[i]);
}
printf("%lld\n",ans-dS[T]);
}
return 0;
}
- 优化后代码 3个 DFS
#include <iostream>
#include <string>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
const ll MAXN =1e5+10;
ll head[MAXN],cnt=0;
struct Edge{
ll next,from,to,cost;
}E[MAXN*2];
ll Scan(){ //输入外挂
ll res=0,flag=0;
char ch;
if((ch=getchar())=='-'){
flag=1;
}else if((ch>='0' && ch<='9')){
res=ch-'0';
}else ;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch-'0');
return flag? -res:res;
}
void _build(ll from,ll to,ll cost){
E[cnt].from=from;
E[cnt].to=to;
E[cnt].cost=cost;
E[cnt].next=head[from]; //链式前向星
head[from]=cnt++;
}
void build(ll from,ll to,ll cost){
_build(to,from,cost);
_build(from,to,cost);
}
ll dS[MAXN*2],dT[MAXN*2];
void Init(){
mem(dS,0);
mem(dT,0);
mem(head,-1);
cnt=0;
}
void dfs1(ll u,ll &S,ll end){ //end为边界
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==end) continue; //防止往回找
dS[to]=max(dS[to],dS[u]+E[i].cost);
dfs1(to,S,u);
}
}
void dfs2(ll u,ll end){
for(ll i=head[u];i+1;i=E[i].next){
ll to=E[i].to;
if(to==end) continue;
dT[to]=dT[u]+E[i].cost;
dfs2(to,u);
}
}
int main(){
ll n;while(~scanf("%lld",&n)){
Init();
for(ll i=0;i<n-1;i++){
ll from,to,cost;
from=Scan();to=Scan();cost=Scan();
build(from,to,cost);
}
ll S=1,T=1;
dfs1(1,S,-1);
T=S;
mem(dS,0); //一定要全部初始化
dfs1(S,T,-1);
dfs2(T,-1);
ll ans=0;
for(ll i=1;i<=n;i++){
ans+=max(dS[i],dT[i]);
}
printf("%lld\n",ans-dS[T]);
}
return 0;
}
PS.另外…湘潭大学XTUOJ的G++有毒会 RE,用Micosoft C++就能过 这个浪费了好多时间 血的教训