zoukankan      html  css  js  c++  java
  • [POI2014]Tourism

    题目大意:
      给定一个$n(nle20000)$条个点,$m(mle25000)$条边的无向图,保证图中最长路径上的点数不超过$10$。对一个点染色的代价是$w_i$。求使得每个结点都被染色或至少有一个相邻结点被染色的最小代价。

    思路:
      由于图中最长路径上的点数不超过$10$,也就是说,对于每一个联通块的任一生成树,其最深结点的深度不超过$10$。考虑三进制状压DP,用$f[i][j]$表示深度为$i$的点,前$i$个深度状态为$j$的最小代价。其中每个状态的第$k$位为$0$则深度为$k$的结点已染色,若为$1$则表示未染色且相邻点也没有染色,若为$2$则表示未染色但是相邻结点有染色。搜索完一棵子树后将状态上传到父结点。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<climits>
     4 #include<algorithm>
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=20001,M=50001,K=10,S=59049;
    13 const int pow[]={1,3,9,27,81,243,729,2187,6561,19683,59049};
    14 bool vis[N];
    15 int w[N],dep[N],h[N],sz;
    16 unsigned f[K][S];
    17 struct Edge {
    18     int to,next;
    19 };
    20 Edge e[M];
    21 inline void add_edge(const int &u,const int &v) {
    22     e[++sz]=(Edge){v,h[u]};h[u]=sz;
    23     e[++sz]=(Edge){u,h[v]};h[v]=sz;
    24 }
    25 inline int bit(const int &x,const int &k) {
    26     return x/pow[k]%3;
    27 }
    28 void dfs(const int &x,const int &d) {
    29     vis[x]=true;
    30     if((dep[x]=d)==0) {
    31         f[0][0]=w[x];
    32         f[0][1]=0;
    33         f[0][2]=INT_MAX;
    34     } else {
    35         std::fill(&f[d][0],&f[d][pow[d+1]],INT_MAX);
    36         for(register int i=0,j=0;i<pow[d];j=++i) {
    37             int b=1;
    38             for(register int k=h[x];k;k=e[k].next) {
    39                 const int &y=e[k].to;
    40                 if(!vis[y]||dep[y]>=d) continue;
    41                 if(bit(i,dep[y])==0) b=2;
    42                 if(bit(i,dep[y])==1) j+=pow[dep[y]];
    43             }
    44             f[d][i+b*pow[d]]=std::min(f[d][i+b*pow[d]],f[d-1][i]);
    45             f[d][j]=std::min(f[d][j],f[d-1][i]+w[x]);
    46         }
    47     }
    48     for(int i=h[x];i;i=e[i].next) {
    49         const int &y=e[i].to;
    50         if(vis[y]) continue;
    51         dfs(y,d+1);
    52         for(register int i=0;i<pow[d+1];i++) {
    53             f[d][i]=std::min(f[d+1][i],f[d+1][i+2*pow[d+1]]);
    54         }
    55     }
    56 }
    57 int main() {
    58     const int n=getint(),m=getint();
    59     for(register int i=1;i<=n;i++) w[i]=getint();
    60     for(register int i=0;i<m;i++) {
    61         add_edge(getint(),getint());
    62     }
    63     int ans=0;
    64     for(register int i=1;i<=n;i++) {
    65         if(vis[i]) continue;
    66         dfs(i,0);
    67         ans+=std::min(f[0][0],f[0][2]);
    68     }
    69     printf("%d
    ",ans);
    70     return 0;
    71 }
  • 相关阅读:
    AppCompatActivity、ActionBarActivity、FragmentActivity和Activity的区别
    Android-Async-Http
    如何在Android studio中同时打开多个工程?
    Multi-threading Android Apps for Multi-core Processors – Part 1 of 2
    Performance Tips
    容器生态系统
    Docker生态不会重蹈Hadoop的覆辙
    Docker生态会重蹈Hadoop的覆辙吗?
    国外牛人的五个Kubernetes学习建议
    Kubernetes基本概念
  • 原文地址:https://www.cnblogs.com/skylee03/p/8669300.html
Copyright © 2011-2022 走看看