2017CCPC中南地区赛 H题(最长路)

题目地址:202.197.224.59/OnlineJudge2/

来自湘潭大学OJ,题号:1267。

这里用到了一个树的直径(树中的最长边)的结论:当你找到一棵树的最长边后,这个树中所有点的最长边必定和这条边的两个端点相连。下面给出证明:

设这条最长边的两个端点分别为B和E;

1.当选择的任意点M在这条最长边上时:如果此时还存在另一个点T,使得MT > max{MB,ME}。则:MT + min{MB,ME} > max{MB,ME} + min{MB,ME} = BE这与题目假设相矛盾。

2.当选择的任意点M不在这条最长边上时:

Α.与它相连的最长边与BE有交点时,假设交于X,则:M的最长边 = MX + X的最长边,而X在BE上,所以M的最长边 = MX + max{XB,XE}即它的最长边终止于BE中的一个点。

B.若无交点,假设M的最长边为MN,则:取BE上一点X,连接MX,有:MN > max{XB,XE} + XM,MN + MX + max{XB,XE} > 2MX + 2max{XB,XE} > BE与题设矛盾

由此,本题思路即为:先找到最长边,然后将其余的n - 2个点到最长边两个端点的距离算出,不断地挑选这n-2个点到两个端点的更长的那个路径,最后加上这条最长路就是所求结果。

下面的代码用C++11提交能过,而用G++则会WA

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define maxn 100005
#define F 0x3f
using namespace std;
struct edge
{
    int len,over;
    edge(int a = 0,int b = 0)
    {
        len = a,over = b;
    }
};
long long dist[3][maxn];
vector<edge> graph[maxn];
inline void init()
{
    for(int i = 1;i < maxn;++i)
        graph[i].clear();
}
queue<int> q;
void bfs(int use,int start)
{
    while(q.size()) q.pop();
    q.push(start);
    dist[use][start] = 0;
    while(q.size()){
        int temp = q.front();
        q.pop();
        for(int i = 0;i < graph[temp].size();++i){
            int length = graph[temp][i].len,nextone = graph[temp][i].over;
            if(dist[use][nextone] == -1){
                dist[use][nextone] = dist[use][temp] + length;
                q.push(nextone);
            }
        }
    }
    return;
}
int main()
{
    int n;
    while(scanf("%d",&n) == 1){
        int start,over,len;
        init();
        for(int i = 0;i < n - 1;++i){
            scanf("%d%d%d",&start,&over,&len);
            graph[start].push_back(edge(len,over));
            graph[over].push_back(edge(len,start));
        }
        int point1,point2;
        memset(dist,-1,sizeof(dist));
        //printf("now dist is %lld\n",dist[0][0]);
        bfs(0,1);
        long long maxone = 0;
        for(int i = 2;i <= n;++i){
            if(dist[0][i] > maxone) maxone = dist[0][i],point1 = i;
        }
        maxone = 0;
        bfs(1,point1);
        for(int i = 1;i <= n;++i){
            if(dist[1][i] > maxone) maxone = dist[1][i],point2 = i;
        }
        bfs(2,point2);
        //printf("point1 is %d and point2 is %d\n",point1,point2);
        long long answer = 0;
        answer += dist[1][point2];
        for(int i = 1;i <= n;++i){
            if(i != point1 && i != point2){
                answer += max(dist[1][i],dist[2][i]);
            }
        }
        if(n == 1) answer = 0;
        printf("%lld\n",answer);
    }
    return 0;
} 
时间: 2024-12-17 06:03:47

2017CCPC中南地区赛 H题(最长路)的相关文章

HDUOJ-------2493Timer(数学 2008北京现场赛H题)

Timer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 445    Accepted Submission(s): 90 Problem Description Recently, some archaeologists discovered an ancient relic on a small island in the Pa

ACM-ICPC 2018徐州网络赛-H题 Ryuji doesn&#39;t want to study

C*M....死于update的一个long long写成int了 心累 不想写过程了 ******** 树状数组,一个平的一个斜着的,怎么斜都行 题库链接:https://nanti.jisuanke.com/t/31460 #include <iostream> #include <cstring> #define ll long long #define lowbit(x) (x & -x) using namespace std; const int maxn =

青岛理工交流赛 H题 素数间隙

13110581088注销 素数间隙 Time Limit: 1000MS Memory limit: 262144K 题目描述 Neko猫是一个很喜欢玩数字游戏的会说话的肥猫,经常会想到很多很好玩的数字游戏,有一天,它想到一个叫做素数间隙的游戏.据Neko猫的定义,素数间隙是两个相邻素数p和q组成的开区间[p, q),所以素数间隙的长度就是q-p. 例如7和11在素数表里是两个相邻的素数,所以7和11的素数间隙的长度为11-7,为4. 现在Neko猫会给你很多个正整数K(1<K≤1299710

ACM-ICPC 2018青岛网络赛-H题

把这题的每个点分成两种情况看,如果是从这个点开始,0算作2,1算作1,如果是中间点或者是结束点,如果和前面的相同看作2,不相同看作1 #include <iostream> #include <string> #include <string.h> using namespace std; int main() { ios::sync_with_stdio(false); int t; cin >> t; while (t--) { int a, b; st

PKU2018校赛 H题 Safe Upper Bound

http://poj.openjudge.cn/practice/C18H 题目 算平均数用到公式\[\bar{x}=\frac{x_1+x_2+x_3+\cdots+x_n}{n}\] 但如果用int型计算,那么\(x_1+x_2+x_3+\cdots+x_n\)可能会超过\(2^{31}-1\) 算6个数的平均数可以这么算 Calculate the average of\(x_1,x_2,x_3\)\[\bar{x}_1=\frac{x_1+x_2+x_3}{3}\]Calculate t

哈尔滨理工大学2016新生赛H题

陈月亮最喜欢的季节就是冬天了,这不看着窗外飘起了雪花,陈月亮开心的跑出屋来看雪.但是迷迷糊糊的陈月亮不知道自己是在做梦还是真的下起了雪.突然她想起了一句话,在真实世界中是没有两片一样的雪花的.于是你的任务就是比较这场雪中的所有雪花,如果出现了两朵完全一致的雪花,则证明陈月亮是在梦中. 每朵雪花用六个整数表示,范围在(1 – 10000000)之间,表示雪花六个花瓣的长度,六个整数的先后出现顺序可能是顺时针顺序也可能是逆时针顺序,并且可能是从任意一个花瓣开始的.比如说对同一个花瓣,描述方法可能是1

2014鞍山现场赛H题HDU5077(DFS减枝+打表)

NAND Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 65    Accepted Submission(s): 14 Problem Description Xiaoqiang entered the "shortest code" challenge organized by some self-claimed a

2017年中国大学生程序设计竞赛-中南地区赛暨第八届湘潭市大学生计算机程序设计大赛游记心得

第一天---------------------------------------------------------------------------------------------------------------------- 一大早六点钟起床开始整理东西,准备出发了(昨晚打CF打到2点,困的要命,要不是要去比赛,我才懒得起这么早呢),该死的碰到了大雨,于是等啊等,等到了七点一十才出门,那时候雨才刚停,我和室友到食堂迅速地吃完早餐以后,在食堂碰到了我的队友yzx,然后跟着他一起到

HDU 5119 Happy Matt Friends(2014北京区域赛现场赛H题 裸背包DP)

虽然是一道还是算简单的DP,甚至不用滚动数组也能AC,数据量不算很大. 对于N个数,每个数只存在两个状态,取 和 不取. 容易得出状态转移方程: dp[i][j] = dp[i - 1][j ^ a[i]] + dp[i - 1][j]; dp[i][j] 的意思是,对于数列 中前 i 个数字,使得 XOR 和恰好为 j 的方案数 状态转移方程中的 dp[i - 1][j] 即表示当前这个数字不取, dp[i - 1][j ^ a[i]] 表示当前这个数字要取. 这道题还是要好好理解阿! sou