poj 3013 Big Christmas Tree

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 3013 Big Christmas Tree相关的知识,希望对你有一定的参考价值。

Big Christmas Tree

题意:输入v个节点和e条边(0 ≤ v, e ≤ 50000) 的图,第二行输入每个节点的权值,之后e行输入每条边的端点和权值;

问是否能找出一棵树,使得树中的边权乘以该边下面的子孙节点权值之和的sigma总和最小;(树以1为根节点)

Sample Input

1

200 10 20 30 40 50 60
1 2 1
2 3 3
2 4 2
3 5 4
3 7 2
3 6 3
1 5 9 (删掉)

Sample Output

1210

分析:如果计算最小乘积时真的就是按照题目给的,对于每条边去累加该边下面的节点的权值之和;但是这样直接被忽悠了。。反过来看,就相当于每个节点计算了几次。。(几次指的是到根节点的边权之和)这样就直接Djistra跑单源最短路即可;使用优先队列,直接确定点的最短路径长,所以可以在djistra中计算出ans;同时还可以看是否是连通图;

ps:注意特判v = 0;这时cnt = 1 > v;

Djistra + priority_queue

技术分享
//Accepted    2804K    141MS
#include <cstdio>
#include <cstring>
#include <utility>
#include <queue>
#include <vector>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define inf 1LL<<40
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+0);
}
const int N = 50050;
typedef __int64 ll;
typedef pair<__int64,int> lli;//距离,编号
#define A first
#define B second
priority_queue<lli , vector<lli> , greater<lli> > q;
int v,val[N];
int head[N<<1],tot;
struct edge{
    int to,w,Next;
}e[N<<1];
void ins(int a,int b,int w = 0)
{
    e[++tot].Next = head[a];
    e[tot].to = b;
    e[tot].w = w;
    head[a] = tot;
}
ll d[N];bool vis[N];
ll Djistra()
{
    ll ans = 0,cnt = 0;
    d[1] = 0;
    q.push(lli{d[1],1});
    while(!q.empty()){
        lli t = q.top();
        q.pop();
        int u = t.B;
        if(vis[u]) continue;
        cnt++;vis[u] = true;
        ans += d[u]*val[u];
        for(int id = head[u];id;id = e[id].Next){
            int v = e[id].to,cost = e[id].w;
            if(d[v] > d[u] + cost){
                d[v] = d[u] + cost;
                q.push(lli{d[v],v});

            }
        }
    }
    if(cnt < v) return -1;
    return ans;
}
int main()
{
    int T,e,kase = 1;
    read1(T);
    while(T--){
        read2(v,e);
        rep1(i,1,v)
            read1(val[i]),d[i] = inf,vis[i] = false;
        MS0(head);tot = 0;
        rep0(i,0,e){
            int a,b,w;
            read3(a,b,w);
            ins(a,b,w);ins(b,a,w);
        }
        if(v <= 1)out(0);
        else{
            while(!q.empty()) q.pop();
            ll ret = Djistra();
            if(ret == -1) printf("No Answer");
            else out(ret);
        }
        puts("");
    }
    return 0;
}
View Code

 

以上是关于poj 3013 Big Christmas Tree的主要内容,如果未能解决你的问题,请参考以下文章

poj 3013 Big Christmas Tree

POJ3013-Big Christmas Tree-最短路

poj3013Big Chrismas Tree——树转换spfa

POJ 3710 Christmas Game

poj3710 Christmas Game

poj 3710 Christmas Game(树上的删边游戏)