zoukankan      html  css  js  c++  java
  • [测试题]gentree

    Description

    给你一个有向连通图G,每点有个权值Di(0<Di),要求生成一棵树根为1号节点的有根树T。对于树中边E,E的代价为所有从根出发的且包含E的路径的终点权值的和。现求生成树T,使得边的代价总和最小。

    Input

    第一行N,M分别为点数,边数。(0<=N <= 20000;0<=M <= 200000)

    接下来M行,每行两个数U,V描述边的两个端点,即从U到V有一条有向边。

    最后一行N个数,顺次给出每个点的权值。

    Output

    一个数,最小代价。

    Sample Input

    5 4

    1 2

    1 3

    3 4

    3 5

    1 2 3 4 5

    Sample Output

    23

    Hint

    样例解释:

    如图只有一种生成树的方法,求得代价为23。

    数据规模:

    所有数据保证不会超过长整型(C++中的int)。

    题解

    归纳发现,算出的总代价就是每个节点在生成树中的深度$×$点权的和。

    我们用贪心的思想,每个点的深度都要尽可能小。那么我们只需以$1$号节点为源点,跑一遍最短路即可。

    由最小生成树的思想,我们易知所有求出的最短路径都在一棵生成树上,满足题意。

     1 #include<map>
     2 #include<queue>
     3 #include<stack>
     4 #include<cmath>
     5 #include<ctime>
     6 #include<cstdio>
     7 #include<string>
     8 #include<cstring>
     9 #include<cstdlib>
    10 #include<iostream>
    11 #include<algorithm>
    12  using namespace std;
    13 const int N=20000;
    14 const int M=200000;
    15 
    16 int n,m,u,v;
    17 struct tt
    18 {
    19     int to,next;
    20 }edge[M+5];
    21 int path[N+5],top;
    22 int ans;
    23 void Add(int u,int v);
    24 
    25 int dist[N+5];
    26 bool vis[N+5];
    27 void SPFA();
    28 
    29 int main()
    30 {
    31     scanf("%d%d",&n,&m);
    32     for (int i=1;i<=m;i++)
    33     {
    34         scanf("%d%d",&u,&v);
    35         Add(u,v);
    36     }
    37     SPFA();
    38     for (int i=1;i<=n;i++)
    39     {
    40         scanf("%d",&u);
    41         ans+=u*dist[i];
    42     }
    43     printf("%d
    ",ans);
    44     return 0;
    45 }
    46 
    47 void Add(int u,int v)
    48 {
    49     edge[++top].to=v;
    50     edge[top].next=path[u];
    51     path[u]=top;
    52 }
    53 void SPFA()
    54 {
    55     memset(dist,127/3,sizeof(dist));
    56     dist[1]=0;
    57     vis[1]=1;
    58     queue<int>Q;
    59     Q.push(1);
    60     while (!Q.empty())
    61     {
    62         for (int i=path[Q.front()];i;i=edge[i].next)
    63         {
    64             if (dist[edge[i].to]>dist[Q.front()]+1)
    65             {
    66                 dist[edge[i].to]=dist[Q.front()]+1;
    67                 if (!vis[edge[i].to])
    68                 {
    69                     Q.push(edge[i].to);
    70                     vis[edge[i].to]=1;
    71                 }
    72             }
    73         }
    74         vis[Q.front()]=0;
    75         Q.pop();
    76     }
    77 }

     

  • 相关阅读:
    树莓派设置CPU运行的核心数为3,保留核心4号
    node+egg中mongdb的一些知识点
    如何提高前端的技能和快速涨薪?
    【安全认证】我的CISSP达成之路
    前端gitLab ci/cd搭建
    flutter调试
    js rgb hex hsv色值转换
    Error waiting for a debug connection: The log reader stopped unexpectedly
    Flutter滑动列表实现
    前端异常监控
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7365435.html
Copyright © 2011-2022 走看看