• HDU


    题意:给你n个寺庙,m个村庄,p条路,现在你要在这n+m个位置中选出若干个位置打井,每个位置打井的费用会告诉你,同时p条路也有修建费用,现在每个寺庙都住着一个和尚,问你最小的费用让这n个和尚都能喝上水。

    思路:可以对照之前做的MST题目(https://www.cnblogs.com/hua-dong/p/11164702.html)。 之前那个题是让所有点都喝上水,让后新建一个0号节点,向所有点连边,边权是打井的费用,然后跑最小生成树。   而本题是让所有寺庙有水,不关心村庄,所以应该是斯坦纳树模型。

    斯坦纳树:使得关键点连通的最小代价。  dp[i][j]代表以i为根,连通状态为j的最小代价。 不停地子集DP+dijkstra....

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=2010;
    const int inf=1e9;
    int Laxt[maxn*7],Next[maxn*7],To[maxn*7],Len[maxn*7],cnt;
    int N,M,dis[maxn][maxn],dp[maxn][maxn],vis[maxn],V;
    void add(int u,int v,int len)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
        Len[cnt]=len;
    }
    void SPFA()
    {
        rep(i,0,V) rep(j,0,V) dis[i][j]=inf;
        rep(i,0,V) {
            queue<int>q;
            dis[i][i]=0;
            q.push(i);
            while(!q.empty()){
                int u=q.front(); q.pop(); vis[u]=0;
                for(int j=Laxt[u];j;j=Next[j]){
                    int v=To[j];
                    if(dis[i][v]>dis[i][u]+Len[j]){
                        dis[i][v]=dis[i][u]+Len[j];
                        if(!vis[v]){vis[v]=1; q.push(v);}
                    }
                }
            }
        }
    
    }
    void solve()
    {
        rep(i,0,N)
         rep(j,0,V) dp[j][1<<i]=dis[i][j];
        rep(i,1,(1<<(N+1))-1){
            if(!((i-1)&i)) continue; //只有一位,不管,上面已经给出。
            rep(j,0,V){
                dp[j][i]=inf;
                for(int k=i;k;k=(k-1)&i)
                dp[j][i]=min(dp[j][i],dp[j][k]+dp[j][i^k]);
            }
            rep(k,0,V){
               if(dp[k][i]==inf) continue;
               rep(j,0,V)
                 dp[j][i]=min(dp[j][i],dp[k][i]+dis[k][j]);
            }
        }
    }
    int main()
    {
        int P,u,v,x;
        while(~scanf("%d%d%d",&N,&M,&P)){
            V=N+M;
            rep(i,0,V) Laxt[i]=0; cnt=0;
            rep(i,1,V){
                scanf("%d",&x);
                add(0,i,x); add(i,0,x);
            }
            rep(i,1,P){
                scanf("%d%d%d",&u,&v,&x);
                add(u,v,x); add(v,u,x);
            }
            SPFA();
            solve();
            printf("%d
    ",dp[0][(1<<(N+1))-1]);
        }
        return 0;
    }
  • 相关阅读:
    你的代码又导致资金损失了?活该!
    rabbitmq实现指定消费者才能消费
    没有绝对,没有百分百
    jenkins构建触发器之Build whenever a snapshot dependency is built
    豁然明白的囧事 之 执行mvn:clean deploy提示401 Unauthorized
    (8/8)RPC方法的参数,能用枚举就请考虑枚举
    abstract 关键字
    练习题------代码块
    代码块
    static 关键字
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11199430.html
Copyright © 2020-2023  润新知