• HDU3311Dig The Wells


    给定N个寺庙,和M个另外的地方。

    然后给定点权,表示在这个点挖水井需要的代价。

    再给定边权,为建造无向边i,j的代价。

    然后求怎样弄最小的代价使得前N个点,就是寺庙都能从挖的井里得到水。

    输入输出格式

    输入格式:

    第1行:三个整数N,M,Q(Q的含义下面有解释)

    第2行:共N+M个整数,第i个数表示在编号为i的地方安装适配器费用Ai

    第3~Q+2行:每行三个整数U,V,C,表示编号为U,V间连接网线的费用为C

    输出格式:

    共1行,1个整数,表示使所有机房连上网的费用最小值。

    输入输出样例

    输入样例#1:
    3 1 3
    1 2 3 4
    1 4 2
    2 4 2
    3 4 4 
    输出样例#1:
    6
    输入样例#2:
    4 1 4
    5 5 5 5 1
    1 5 1
    2 5 1
    3 5 1
    4 5 1 
    输出样例#2:
    5

    说明

    样例解释:

    对于样例1:直接在每个机房安装适配器,开销最小,为1+2+3=6。

    对于样例2:在唯一一个非机房的教室安装适配器,并从此处接网线到各个机房,开销最小,为1+1+1+1+1=5。

    数据规模:

    20%的数据有N=1;

    另20%的数据有N=2;

    另20%的数据有N=3;

    100%的数据有1<=N<=5,1<=M<=1000,M<=Q<=5000,1<=A,C<=10000。

    斯坦纳树的应用:

    与模板相比,多了点权的设定,即一个联通块要有一个点权

    方法很简单,设一个0节点,i点权值为x则加边(0,i,x),求部分点最小生成树(斯坦纳树)

    斯坦纳树的概念和实现方法:http://blog.csdn.net/gzh1992n/article/details/9119543

    注意此代码没有考虑多组数据

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 struct Node
     7 {
     8     int next,to,dis;
     9 }edge[200001];
    10 int q[100001],num,head[100001],dist[2001][2001],n,m,qq,f[(1<<7)][2001];
    11 bool vis[100001];
    12 void add(int u,int v,int dis)
    13 {
    14     num++;
    15     edge[num].next=head[u];
    16     head[u]=num;
    17     edge[num].to=v;
    18     edge[num].dis=dis;
    19 }
    20 void bfs(int x)
    21 {int h,t,i;
    22     q[1]=x;
    23     h=0;t=1;
    24     dist[x][x]=0;
    25     memset(vis,0,sizeof(vis));
    26     while (h<t)
    27     {
    28         h++;
    29         int u=q[h];
    30         vis[u]=0;
    31          for (i=head[u];i;i=edge[i].next)
    32          {
    33              int v=edge[i].to;
    34              if (dist[x][v]>dist[x][u]+edge[i].dis)
    35              {
    36                  dist[x][v]=dist[x][u]+edge[i].dis;
    37                  if (vis[v]==0)
    38                  {
    39                      t++;
    40                      q[t]=v;
    41                      vis[v]=1;
    42                  }
    43              }
    44          }
    45     }
    46 }
    47 int main()
    48 {int i,j,x,u,v,c,l;
    49     cin>>n>>m>>qq;
    50     memset(dist,127/3,sizeof(dist));
    51     for (i=1;i<=n+m;i++)
    52     {
    53         scanf("%d",&x);
    54         add(0,i,x);add(i,0,x);
    55     }
    56      for (i=1;i<=qq;i++)
    57      {
    58          scanf("%d%d%d",&u,&v,&c);
    59          add(u,v,c);add(v,u,c);
    60      }
    61      for (i=0;i<=n+m;i++)
    62      bfs(i);
    63      memset(f,127/3,sizeof(f));
    64      for (i=0;i<=n;i++)
    65      {
    66           for (j=0;j<=n+m;j++)
    67           {
    68               f[1<<i][j]=dist[i][j];
    69           }
    70      }
    71      for (i=0;i<=n+m;i++)
    72      {
    73          f[0][i]=0;
    74      }
    75      for (int sta=1;sta<(1<<(n+1));sta++) if (sta&(sta-1))
    76     {
    77         for (int i=0;i<=n+m;i++)
    78             for (int sub=sta;sub;sub=(sub-1)&sta)
    79                 if (f[sta][i]>f[sub][i]+f[sta^sub][i])
    80                     f[sta][i]=f[sub][i]+f[sta^sub][i];
    81         for (int i=0;i<=n+m;i++)
    82             for (int j=0;j<=n+m;j++)
    83                 if (f[sta][i]>f[sta][j]+dist[j][i])
    84                     f[sta][i]=f[sta][j]+dist[j][i];
    85     }
    86     cout<<f[(1<<n+1)-1][0];
    87 }
  • 相关阅读:
    .net framework缓存遍历
    R语言中统计数据框所有项中的并集
    R语言中在数据框中批量替换指定项
    R语言中 %in%用法
    windows中如何查看端口占用情况、端口是否开启
    R语言中rbind函数和cbind的用法
    linux系统shell实现统计 plink文件基因频率
    linux 系统中实现列转行 及 行转列
    linux系统中向行末添加换行符
    R语言中实现方差和标准差
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7252521.html
Copyright © 2020-2023  润新知