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 }
原文地址:https://www.cnblogs.com/Y-E-T-I/p/7252521.html