poj3013 Big Christmas Tree --- 最短路

来源:互联网 发布:json在线 编辑:程序博客网 时间:2024/04/29 08:54

我都不好意思在标题上写这是最短路

这题挺有意思,关键在于把题目所求的量转换为最短路问题。


题意:

给一个无向图,每个结点有权值p[i],每条边有权值w[i]

求使这颗树所有顶点与根节点1联通的最小花费,

最小花费=∑w[i]×∑p[i]

第一个∑是所有边,第二个∑是该边下所有结点的权值和

思路:

通过推导可以发现,对于每个结点,它被算入的花费为 p[i]*d[i],

d[i]为该结点到根结点的距离。

于是豁然开朗了吧。。水题一道

唯一的坑点是要int64,而且inf要足够大


#include<cstdio>#include<cstring>#include<queue>#include<iostream>using namespace std;const ll inf=1ll<<60;//坑死!这题inf必须足够大#define N 50010#define M 100010struct node{    int v,next;    ll w;}e[M];int vis[N],n,m,head[N],h;ll d[N],p[N];void addedge(int a,int b,ll c){    e[h].v=b;    e[h].w=c;    e[h].next=head[a];    head[a]=h++;}int spfa(int st){    memset(vis,0,sizeof vis);    for(int i=0;i<=n;i++)        d[i]=inf;    d[st]=0;    vis[st]=1;    queue<int> q;    q.push(st);    int x,i,v;    while(!q.empty())    {        x=q.front();        q.pop();        vis[x]=0;        for(i=head[x];i!=-1;i=e[i].next)        {            v=e[i].v;            if(d[v]>d[x]+e[i].w)            {                d[v]=d[x]+e[i].w;                if(!vis[v])                {                    vis[v]=1;                    q.push(v);                }            }        }    }}void init(){    memset(head,-1,sizeof head);    h=0;}int main(){    int t,a,b,i;    ll ans,c;    scanf("%d",&t);    while(t--)    {        init();        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++)            cin>>p[i];        while(m--)        {            scanf("%d%d",&a,&b);            cin>>c;            addedge(a,b,c);            addedge(b,a,c);        }        spfa(1);        ans=0;        int flag=1;        for(i=2;i<=n;i++)        {            if(d[i]==inf)            {                flag=0;                break;            }            ans+=(d[i]*p[i]);        }        if(!flag)  printf("No Answer\n");        else cout<<ans<<endl;    }    return 0;}


0 0
原创粉丝点击