zoukankan      html  css  js  c++  java
  • 最小权路径集问题 解题题报告

    最小权路径集问题

    自闭了,sb斯坦纳树题没看出来,以此纪念..

    (dp_{s,i})表示点(i)联通关键点集合(s)的最小代价,转移显然。

    [dp_{S,i}=min_{Q+T=S}dp_{Q,i}+dp_{T,i}\ dp_{S,i}=min_{E(i,j)in G}dp_{S,j}+mathtt {edge_{i,j}} ]

    (S)分层,每层跑最短路即可。

    最后再拿个dp合并斯坦纳森林


    Code:

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    using std::max;
    const int SIZE=1<<21;
    char ibuf[SIZE],*iS,*iT;
    //#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
    #define gc() getchar()
    template <class T>
    void read(T &x)
    {
        int f=0;x=0;char c=gc();
        while(!isdigit(c)) f|=c=='-',c=gc();
        while(isdigit(c)) x=x*10+c-'0',c=gc();
        if(f) x=-x;
    }
    void ckmin(int &x,int y){x=x<y?x:y;}
    const int inf=0x3f3f3f3f;
    const int N=105;
    int head[N],to[N*N],Next[N*N],edge[N*N],cnt;
    void add(int u,int v,int w)
    {
        to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
    }
    int n,m,k,dp[1<<10][N],aya[1<<5];
    std::queue <int> q;
    void spfa(int s)
    {
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=Next[i])
            {
                int v=to[i],w=edge[i];
                if(dp[s][v]>dp[s][now]+w)
                {
                    dp[s][v]=dp[s][now]+w;
                    q.push(v);
                }
            }
        }
    }
    int main()
    {
        read(n),read(m),read(k);
        for(int u,v,w,i=1;i<=m;i++)
        {
            read(u),read(v),read(w);
            add(u,v,w),add(v,u,w);
        }
        memset(dp,0x3f,sizeof dp);
        for(int i=1;i<=n;i++)
        {
            if(i<=k) dp[1<<i-1][i]=0;
            dp[0][i]=0;
        }
        for(int s=1;s<1<<k;s++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int t=s;t;t=t-1&s)
                    ckmin(dp[s][i],dp[t][i]+dp[s^t][i]);
                if(dp[s][i]<inf) q.push(i);
            }
            spfa(s);
            for(int i=1;i<=n;i++)
                ckmin(dp[s][0],dp[s][i]);
        }
        memset(aya,0x3f,sizeof aya);
        aya[0]=0;
        k>>=1;
        for(int s=1;s<1<<k;s++)
        {
            for(int t=s;t;t=t-1&s)
            {
                int it=0;
                for(int i=0;i<k;i++)
                    if(t>>i&1)
                        it|=1<<(i<<1),it|=1<<(i<<1|1);
                ckmin(aya[s],aya[s^t]+dp[it][0]);
            }
        }
        if(aya[(1<<k)-1]==inf) puts("-1");
        else printf("%d
    ",aya[(1<<k)-1]);
        return 0;
    }
    

    2019.5.23

  • 相关阅读:
    【HDOJ】2267 How Many People Can Survive
    【HDOJ】2268 How To Use The Car
    【HDOJ】2266 How Many Equations Can You Find
    【POJ】2278 DNA Sequence
    【ZOJ】3430 Detect the Virus
    【HDOJ】2896 病毒侵袭
    求奇数的乘积
    平方和与立方和
    求数列的和
    水仙花数
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10911603.html
Copyright © 2011-2022 走看看