2017 江苏省赛JSCPC H(贪心,prim)

题目描述

给你一棵树,两两节点间有一个距离 ci c i ,现在要重建地图,任意两个顶点间的花费是他们之间的最短路,建最大生成树求花费.

分析

这题比赛的时候没有做出来,赛后看题解原来很简单,想象prim的建树过程每次找剩余边集合中的最大距离.显然我们首先找到直径 v0,v1 v 0 , v 1 肯定作为第一条边然后照剩余点,对于剩下的每个点他要莫加到 v0,v1 v 0 , 要 莫 加 到 v 1 ,因为可以证明他到任意点的距离不会超过 max(dist(v,v0),dist(v,v1)) m a x ( d i s t ( v , v 0 ) , d i s t ( v , v 1 ) ) ,可以用反正法来证明这个结论因为 v0,v1 v 0 , v 1 是直径

AC code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define pb push_back
#define mp make_pair
#define PI acos(-1)
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define INF64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
const int MAX_P = 2e4+10;
const int maxn = 1e5+10;
const int MAX_V = 5e5+10;
const double eps = 1e-8;
typedef long long LL;
typedef long double DB;
typedef pair<int,int> Pair;

struct Edge{
    int from,to,cost;
};

Edge E[maxn*2];
int ne;
std::vector<int> G[maxn];
void add_edge(int u,int v,int cost){
    E[ne++] = Edge{u,v,cost};
    G[u].pb(ne-1);
    E[ne++] = Edge{v,u,cost};
    G[v].pb(ne-1);
}

LL d[2][maxn];
bool vis[maxn];
void bfs(int s,LL *dist){
    dist[s] = 0;
    memset(vis,0,sizeof(vis));
    vis[s] = true;
    queue<int> Q;
    Q.push(s);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for(int i=0 ; iif(!vis[e.to]){
                dist[e.to] = dist[u] + e.cost;
                vis[e.to] = true;
                Q.push(e.to);
            }
        }
    }
}


int main() {
    int n;
    while (scanf("%d",&n ) != EOF) {
        for(int i=1 ; i<=n ; ++i)G[i].clear();
        ne = 0;
        for(int i=0 ; i1 ; ++i){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c );
            add_edge(a,b,c);
        }
        LL ans =0;
        bfs(1,d[0]);
        int v0 = 1;
        for(int i=1 ; i<=n ; ++i)
            if(d[0][v0] < d[0][i])v0 = i;
        bfs(v0,d[0]);
        int v1 = 1;
        for(int i=1 ; i<=n ; ++i){
            //std::cout << d[0][i] << '\n';
            if(d[0][v1] < d[0][i])v1 = i;
        }
        bfs(v1,d[1]);
        ans = d[0][v1];
        for(int i=1 ; i<=n ; ++i){
            //std::cout << d[1][i] << '\n';
            if(i != v0 && i != v1){
                ans += max(d[0][i],d[1][i]);
            }
        }
        //std::cout << v0<<" " << v1 << '\n';
        printf("%lld\n",ans );
    }


    return 0;
}

你可能感兴趣的:(算法&数据结构)