现在的位置: 首页 > 综合 > 正文

POJ 3013 Big Christmas Tree – from lanshui_Yang

2018年02月21日 ⁄ 综合 ⁄ 共 1485字 ⁄ 字号 评论关闭

        题目大意:给你 n 个节点,编号从1 到 n ,节点 1 为根节点,并且每个节点都有一个重量 w ,现在要在这些点之间建设公路,要求必须包含所有节点并且使整个图连通,总费用为  每条边的单价 * (该边所有子节点的重量之和) 。其实这是一个最短路的问题,经过推倒,总费用 = 每个节点的重量 * 该节点到根节点(节点1)的最短路径。

        Ps:此题卡精度 , 需用long long , int 范围不够, double 精度不够 。

请看代码:

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#define mem(a , b) memset(a , b , sizeof(a))
using namespace std ;
const int MAXN = 5e4 + 5 ;
const long long INF = 0x7fffffffffffffff ;
long long dis[MAXN] ;
int w[MAXN] ;
struct Edge
{
    int adj ;
    int d ;
    int next ;
} e[MAXN * 2] ;
int n , se ;
int ecnt ;
int head[MAXN] ;
bool inq[MAXN] ;
int root ;
void chu()
{
    ecnt = 0 ;
    mem(head , -1) ;
    mem(inq , 0) ;
    root = 1 ;
}
void init()
{
    scanf("%d%d" , &n , &se) ;
    int i ;
    for(i = 1 ; i <= n ; i ++)
    {
        scanf("%d" , &w[i]) ;
    }
    for(i = 0 ; i < se ; i ++)
    {
        int a , b , d ;
        scanf("%d%d%d" , &a , &b , &d) ;
        e[ecnt].adj = b ;
        e[ecnt].d = d ;
        e[ecnt].next = head[a] ;
        head[a] = ecnt ;

        ecnt ++ ;
        e[ecnt].adj = a ;
        e[ecnt].d = d ;
        e[ecnt].next = head[b] ;
        head[b] = ecnt ;
        ecnt ++ ;
    }
}
queue<int> q ;
void spfa()
{
    while (!q.empty()) q.pop() ;
    q.push(root) ;
    inq[root] = true ;
    int tmp ;
    while (!q.empty())
    {
        tmp = q.front() ;
        q.pop() ;
        inq[tmp] = false ;
        int i ;
        for(i = head[tmp] ; i != -1 ; i = e[i].next)
        {
            Edge t = e[i] ;
            int tv ;
            tv = t.adj ;
            int td = t.d ;
            if(dis[tmp] < INF && dis[tmp] + td < dis[tv])
            {
                dis[tv] = dis[tmp] + td ;
                if(!inq[tv])
                {
                    inq[tv] = true ;
                    q.push(tv) ;
                }
            }
        }
    }
}
void solve()
{
    if(n == 0  || n == 1) {
        printf("0\n") ;
        return ;
    }
    int i ;
    for(i = 1 ; i <= n ; i ++)
    {
        dis[i] = INF ;
    }
    dis[1] = 0 ;
    spfa() ;
    long long ans = 0 ;
    for(i = 1;  i <= n ; i ++)
    {
        if(dis[i] == INF)
        {
            printf("No Answer\n") ;
            return ;
        }
        ans += w[i] * dis[i] ;
    }
    printf("%lld\n" , ans) ;
}
int main()
{
    int T ;
    scanf("%d" , &T) ;
    while (T --)
    {
        chu() ;
        init() ;
        solve() ;
    }
    return 0 ;
}

抱歉!评论已关闭.