poj 3013 Big Christmas Tree Djistra

Big Christmas Tree

题意:图中每个节点和边都有权值,图中找出一颗树,树根为1使得 Σ(树中的节点到树根的距离)*(以该节点为子树的所有节点的权值之和) 结果最小;

分析:直接求出每个节点到树根的最短距离距离,之后乘上自身节点的权值求和即可;

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

 Djistra + heap

ps:heap中的最后的位置赋值要放在最后,不好直接在break中,因为可能是出边界了,而没有赋到需要的值;

//4116K    125MS    G++    2869B    
#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
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];
lli heap[N],q[N];int _cnt;
bool comp(lli x,lli y)
{
    return x.A < y.A;//最小堆
}
inline void push(const lli x)
{
    heap[++_cnt] = x;
    int son,fa;
    for(son = _cnt,fa = son>>1;fa >= 1;son = fa,fa = son>>1){
        if(comp(x,heap[fa]))
            heap[son] = heap[fa];
        else    break;
    }
    heap[son] = x;
}
inline lli top()
{
    return heap[1];
}
inline void pop()
{
    lli tmp =  heap[1] = heap[_cnt--];
    int son ,fa;
    for(fa = 1,son = fa<<1;son <= _cnt;fa = son,son = fa<<1){
        if(son < _cnt && comp(heap[son|1],heap[son]))
            son++;
        if(comp(tmp,heap[son]))break;
        else heap[fa] = heap[son];
    }
    heap[fa] = tmp;
}
ll Djistra()
{
    ll ans = 0,cnt = 0;
    d[1] = 0;
    push(lli{d[1],1});
    while(_cnt){
        lli t = top();
        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;
                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{
            _cnt = 0;
            ll ret = Djistra();
            if(ret == -1) printf("No Answer");
            else out(ret);
        }
        puts("");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/hxer/p/5186803.html