自爆魂

博客园 首页 新随笔 联系 订阅 管理

http://poj.org/problem?id=3013

给出n个点,m个边。给出每个点的权值,每个边的权值。在m条边中选n-1条边使这n个点成为一棵树,root=1,求这棵树的最小费用,费用=树上每条边*子树中各顶点的权值。


思路:转化一下,发现每条边*子树中各定点的权值=各个点*点到根的最短路,于是转化成了root到各个点的最短路,又到不了的点则说明无法建树。

#pragma comment(linker, "/STACK:36777216")
#pragma GCC optimize ("O2")
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
#define clr1(x) memset(x,-1,sizeof(x))
#define eps 1e-9
const double pi = acos(-1.0);
typedef long long LL;
typedef unsigned long long ULL;
const int modo = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int inf = 0x3fffffff;
const LL _inf = 1e18;
const int maxn = 50005,maxm = 50005;
struct edge{
    int v,w,next;
    edge(){};
    edge(int vv,int ww,int nnext):v(vv),w(ww),next(nnext){};
}e[maxm<<1];
int head[maxn],inq[maxn],vw[maxn];
LL dist[maxn];
int n,m,ecnt;
void init()
{
    clr1(head);
    ecnt = 0;
    fill(dist,dist+maxn,_inf);
    clr0(inq);
}
void add(int u,int v,int w)
{
    e[ecnt] = edge(v,w,head[u]);
    head[u] = ecnt++;
    e[ecnt] = edge(u,w,head[v]);
    head[v] = ecnt++;
}
void spfa(int src)
{
    queue<int> q;
    q.push(src);dist[src] = 0,inq[src] = 1;
    while(!q.empty()){
        int cur = q.front();
        q.pop();inq[cur] = 0;
        for(int i = head[cur];i != -1;i = e[i].next){
            int nxt = e[i].v;
            if(dist[nxt] > dist[cur] + e[i].w){
                dist[nxt] = dist[cur] + e[i].w;
                if(!inq[nxt])
                    inq[nxt] = 1,q.push(nxt);
            }
        }
    }
}
void work()
{
    LL ans = 0;
    for(int i = 2;i <= n;++i){
        if(dist[i] >= _inf){
            puts("No Answer");
            return ;
        }
        ans += dist[i] * vw[i];
    }
    printf("%I64d\n",ans);
}
int main(){
    int u,v,w,_;
    RD(_);
    while(_--){
        RD2(n,m);
        init();
        for(int i = 1;i <= n;++i)
            RD(vw[i]);
        while(m--){
            RD3(u,v,w);
            add(u,v,w);
        }
        spfa(1);
        work();
    }
    return 0;
}


posted on 2014-11-01 14:36  自爆魂  阅读(154)  评论(0编辑  收藏  举报