• HDU 3311 Dig The Wells(斯坦纳树)


    【题目链接】

        http://acm.hdu.edu.cn/showproblem.php?pid=3311

    【题意】

        给定k座庙,n个其他点,m条边,点权代表挖井费用,边权代表连边费用,问使得k座庙里的所有和尚都能吃到水的最小费用。

    【思路】

        首先一个相连的块里只要有口井就能保证块里的和尚有水。所以这个题目标并不是要让k个点连通,但我们可以转化一下。

        在原图的基础上我们添加0号结点,由0号结点向所有的点连边为该点的点权,代表挖井的费用,从而保证每个块里都有井,则问题转化为求以0为根包含k个点的斯坦纳树。

      模板可以上了。

        奇技淫巧系列。。。

    【代码】

     1 #include<set>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
    10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    11 using namespace std;
    12 
    13 typedef long long ll;
    14 const int N = 1e3+10;
    15 const int M = 2e4+10;
    16 const int inf = 0xf0f0f0f;
    17 const int P = 10;
    18 
    19 ll read() {
    20     char c=getchar();
    21     ll f=1,x=0;
    22     while(!isdigit(c)) {
    23         if(c=='-') f=-1; c=getchar();
    24     }
    25     while(isdigit(c))
    26         x=x*10+c-'0',c=getchar();
    27     return x*f;
    28 }
    29 struct Edge { int v,w,nxt;
    30 }e[M];
    31 int en=1,front[N];
    32 void adde(int u,int v,int w) 
    33 {
    34     e[++en]=(Edge){v,w,front[u]}; front[u]=en;
    35 }
    36 
    37 int n,m,K;
    38 int f[1<<P][N];
    39 queue<int> q; int inq[N];
    40 
    41 void spfa(int* dis) 
    42 {
    43     while(!q.empty()) {
    44         int u=q.front(); q.pop();
    45         inq[u]=0;
    46         trav(u,i) {
    47             int v=e[i].v;
    48             if(dis[v]>dis[u]+e[i].w) {
    49                 dis[v]=dis[u]+e[i].w;
    50                 if(!inq[v])
    51                     inq[v]=1,q.push(v);
    52             }
    53         }
    54     }
    55 }
    56 
    57 int main()
    58 {
    59     while(scanf("%d%d%d",&K,&n,&m)==3) {
    60         en=1;
    61         memset(front,0,sizeof(front));
    62         int rt=0;
    63         n+=K;
    64         FOR(i,1,n) {
    65             int w=read();
    66             adde(rt,i,w),adde(i,rt,w);
    67         }
    68         FOR(i,1,m) {
    69             int u=read(),v=read(),w=read();
    70             adde(u,v,w),adde(v,u,w);
    71         }
    72         memset(f,0xf,sizeof(f));
    73         FOR(i,0,K) f[1<<i][i]=0;
    74         int all=1<<(K+1);
    75         FOR(st,1,all-1) {
    76             FOR(i,0,n) {
    77                 for(int s=st&(st-1);s;s=(s-1)&st)
    78                     f[st][i]=min(f[st][i],f[s][i]+f[st^s][i]);
    79                 if(f[st][i]!=inf) q.push(i),inq[i]=1;
    80             }
    81             spfa(f[st]);
    82         }
    83         printf("%d
    ",f[all-1][rt]);
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    算法导论2.37答案
    算法导论2.37的算法
    heavy dark读《《暗时间》》
    深入SetOP2函数
    c++标准库都有哪些文件
    c++ sort函数的用法
    深入char转换为int/unsigned int的内部机制分析
    顺序容器之vector
    java的动态代理机制详解
    java.lang.IllegalStateException: Web app root system property already set to different value
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5301747.html
Copyright © 2020-2023  润新知