zoukankan      html  css  js  c++  java
  • POJ3013 Big Christmas Tree(最短路径树)

    题目大概说给一张点和边都有权的图,现在要求其一棵以1结点为根的生成树使树的边权和最小,树边权 = 对应的图边权 * 树边末端点为根的子树所有结点对于图顶点的点权和。

    要求∑(边权*子树点权和),等价于求∑(点权*点到根路径上的边权和)。

    而如果在图中各个点到根都存在最短路,那么最短路的边一定能构造出一棵生成树。一个构造方法就是在进行最短路的松弛操作时记录各点是从哪点转移的,而各点的这个前驱是唯一的这就对应着各点的父结点。这就是最短路径树。

    那么这一题直接求各个点到1点的最短路,最后乘一下加一下就OK了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 #define INF (1LL<<60)
     7 #define MAXN 55555
     8 #define MAXM 55555*2
     9 
    10 struct Edge{
    11     int v,w,next;
    12 }edge[MAXM];
    13 int NE,head[MAXN];
    14 void addEdge(int u,int v,int w){
    15     edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
    16     head[u]=NE++;
    17 }
    18 
    19 long long d[MAXN];
    20 bool vis[MAXN];
    21 bool SPFA(int n){
    22     for(int i=1; i<=n; ++i){
    23         d[i]=INF; vis[i]=0;
    24     }
    25     d[1]=0; vis[1]=1;
    26     queue<int> que;
    27     que.push(1);
    28     while(!que.empty()){
    29         int u=que.front(); que.pop();
    30         for(int i=head[u]; i!=-1; i=edge[i].next){
    31             int v=edge[i].v;
    32             if(d[v]>d[u]+edge[i].w){
    33                 d[v]=d[u]+edge[i].w;
    34                 if(!vis[v]){
    35                     vis[v]=1;
    36                     que.push(v);
    37                 }
    38             }
    39         }
    40         vis[u]=0;
    41     }
    42     for(int i=1; i<=n; ++i){
    43         if(d[i]==INF) return 0;
    44     }
    45     return 1;
    46 }
    47 
    48 int weight[MAXN];
    49 int main(){
    50     int t,n,m,a,b,c;
    51     scanf("%d",&t);
    52     while(t--){
    53         scanf("%d%d",&n,&m);
    54         for(int i=1; i<=n; ++i){
    55             scanf("%d",weight+i);
    56         }
    57         NE=0;
    58         memset(head,-1,sizeof(head));
    59         while(m--){
    60             scanf("%d%d%d",&a,&b,&c);
    61             addEdge(a,b,c);
    62             addEdge(b,a,c);
    63         }
    64         if(!SPFA(n)){
    65             puts("No Answer");
    66             continue;
    67         }
    68         long long ans=0;
    69         for(int i=1; i<=n; ++i){
    70             ans+=d[i]*weight[i];
    71         }
    72         printf("%lld
    ",ans);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    第五章:向量运算
    第四章:向量
    第三章:多坐标系
    近期一些学习的随笔
    2020高考游记
    寒假集训好题记录
    STL基本用法的一些记录
    2020暑假集训做题记录——数据结构
    2020.12.13~2020.12.20做题记录
    2020.11.30~2020.12.6 做题记录
  • 原文地址:https://www.cnblogs.com/WABoss/p/5475577.html
Copyright © 2011-2022 走看看