POJ--3013--Big Christmas Tree【dijkstra_heap】

题意:要造一个圣诞树(可以想象成倒过来的树结构),有n个节点,m条边,并告诉你边的信息,两条边之间有个单位造价,

一条树枝的造价=它上面的节点的重量以及节点子树的重量 * 这条树枝的单位造价。

需求出造这个圣诞树的最小造价,也有可能造不出。

画画图可以看出,总造价 = 每一点的重量 * 它到节点的最短路径,所以这道题其实就是个最短路

题目比较坑,dist数组会越界,需用long long,并且INF不能以int的最大值来赋值。边也不是他给的5W条,我开到20W才AC

我用了dijkstra+heap的写法,之前也不会,越看越像spfa把队列改成了优先队列,实际上也是这样,但是经过这样处理每一次入队都会处理出对于这个节点来说的最优解,可以把spfa的k次入队减为1次入队,缩短了时间。

不过我还是比较喜欢用我自己的说法:dijkstra+heap打着堆优化的幌子穿着dijkstra的外衣干着spfa的事。

开玩笑,实际上速度能快很多。

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 50010
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct EDGE{
    int u,w,next;
}edge[MAXN*4];
struct NODE{
    int u,dis;
    bool operator < (const NODE &t) const{
        return t.dis < dis;
    }
};
int head[MAXN],vis[MAXN],w[MAXN];
long long dist[MAXN];
int n,m,cnt;
void add_edge(int a,int b,int c){
    edge[cnt].u = b;
    edge[cnt].w = c;
    edge[cnt].next = head[a];
    head[a] = cnt++;
}
void dijkstra_heap(){
    int i,j;
    NODE t1,t2;
    for(i=1;i<=n;i++)   dist[i] = 100000000000000LL;
    dist[1] = 0;
    priority_queue<NODE>q;
    t1.u = 1;
    t1.dis = 0;
    q.push(t1);
    while(!q.empty()){
        t1 = q.top();
        q.pop();
        if(vis[t1.u]==1)  continue;
        vis[t1.u] = 1;
        for(i=head[t1.u];i!=-1;i=edge[i].next){
            int x = edge[i].w;
            if(dist[t1.u]+x<dist[edge[i].u]){
                dist[edge[i].u] = dist[t1.u] + x;
                t2.dis = dist[edge[i].u];
                t2.u = edge[i].u;
                q.push(t2);
            }
        }
    }
}

int main(){
    //freopen("11.txt","r",stdin);
    //freopen("22.txt","w",stdout);
    int t,i,j,a,b,c;
    long long ans;
    scanf("%d",&t);
    while(t--){
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt = 0;
        ans = 0;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            scanf("%d",&w[i]);
        }
        for(i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&c);
            add_edge(a,b,c);
            add_edge(b,a,c);
        }
        dijkstra_heap();
        int flag = 1;
        for(i=2;i<=n;i++){
            if(dist[i]==100000000000000LL){
                flag = 0;
                break;
            }
            ans += dist[i] * w[i];
            //cout<<i<<" "<<dist[i]<<" "<<w[i]<<endl;
        }
        if(flag)    printf("%I64d\n",ans);
        else    puts("No Answer");
    }
    return 0;
}

POJ--3013--Big Christmas Tree【dijkstra_heap】

时间: 2024-09-30 02:19:08

POJ--3013--Big Christmas Tree【dijkstra_heap】的相关文章

POJ 3013 Big Christmas Tree【最短路变形,DIjkstra堆优化+spfa算法】

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23064   Accepted: 4987 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n,树根为编号1,选择一些边,使得所有节点构成一棵树,选择边的代价是(子孙的点的重量)×(这条边的价值).求代价最小多少. 分析: 单看每个点被计算过的代价,很明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 不过坑点还是很多的. 点的数量高达5w个,用矩阵存不行,只能用边存. 还有路径和结

POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)

POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意: 圣诞树是由n个节点和e个边构成的,点编号1-n.树根为编号1,选择一些边.使得全部节点构成一棵树.选择边的代价是(子孙的点的重量)×(这条边的价值). 求代价最小多少. 分析: 单看每一个点被计算过的代价,非常明显就是从根到节点的边的价值.所以这是个简单的单源最短路问题. 只是坑点还是非常多的. 点的数量高达5w个,用矩阵存不行.仅仅能用边存. 还

poj 3013 Big Christmas Tree (dij+优先队列优化 求最短路)

模板 题意:给你一个图,1总是为根,每个边有单位价值,每个点有权重. 每条边的价值 = sum(后继节点权重)*边的单位价值. 求树的最小价值,即构成一棵树的n-1条边的最小价值. 算法: 1.因为每个边的价值都要乘以后来访问的节点的权重,而走到后来访问的点必经过这条边. 实际上总价值就是  到每个点的最短路径*这个点的权重. 2.但是这个题 数据量真的太大了,50000个点,50000条边. 写普通的dij算法tle. 必须加优先队列优化- - 据说spfa也能过,但是spfa算法不稳定- -

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 分析:如果计算最小乘

poj 3013 Big Christmas Tree (dij+优先级队列优化 求最短)

模板 意甲冠军:给你一个图,1始终根,每一方都有单价值,每个点都有权重新. 每个边缘的价格值 = sum(后继结点重)*单价方值. 最低价格要求树值,它构成了一棵树n-1条边的最小价值. 算法: 1.由于每一个边的价值都要乘以后来訪问的节点的权重.而走到后来訪问的点必经过这条边. 实际上总价值就是  到每一个点的最短路径*这个点的权重. 2.可是这个题 数据量真的太大了.50000个点,50000条边. 写普通的dij算法tle. 必须加优先队列优化- - 据说spfa也能过.可是spfa算法不

SPFA/Dijkstra POJ 3013 Big Christmas Tree

题目传送门 题意:找一棵树使得造价最少,造价为每个点的子节点造价和*边的造价和 分析:最短路跑出1根节点到每个点的最短边权值,然后每个点的权值*最短边距和就是答案,注意INF开足够大,n<=1特判.Dijkstra 和 SPFA都行 代码: #include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <vector> #includ

poj 3031 Big Christmas Tree(水spfa)

http://poj.org/problem?id=3013 题意: Because of a technical difficulty, price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).这句话一直没看懂.后面还以为是最小生成树. 正确题意是:给一个无向图,计算每个点到1节点的最短路径(dis[i]) * 每个节点的weights之和. 注意:边权值等要用__

poj 3009 Curling 2.0 【DFS】

题意:从2出发,要到达3, 0可以通过,碰到1要停止,并且1处要变成0, 并且从起点开始沿着一个方向要一直前进,直至碰到1(或者3)处才能停止,(就是反射来反射去知道反射经过3).如果反射10次还不能到达3,就输出-1. 策略:深搜. 易错点,方向不容易掌握,并且,出题人把n, m顺序反了. 代码: #include<stdio.h> #include<string.h> int map[25][25]; int ans, n, m; const int dir[4][2] = {