zoukankan      html  css  js  c++  java
  • [atARC078F]Mole and Abandoned Mine

     注意到最终图的样子可以看作一条从1到$n$的路径,以及删去这条路径上的边后,路径上的每一个点所对应的一个连通块

    考虑dp,令$f_{S,i}$表示当前1到$n$路径上的最后一个点以及之前点(包括$i$)所对应连通块的并,转移考虑枚举下一个点以及其对应的连通块,即$f_{Scup T,j}=min(f_{S,i}+sum(S,T)-len(i,j))$

    (其中$len(i,j)$表示$(i,j)$这条边的长度,$sum(S,T)=sum_{xin S,yin T,(x,y)in E}len(x,y)$)

    初始状态为$f_{S,1}=0$(其中$1in S$且$S$的导出子图连通),$f_{other}=infty$

    转移条件为$(i,j)in E$、$jin T$、$Scap T=empty$且$T$的导出子图连通,因此转移复杂度为$o(n^{2}3^{n})$(关于$T$导出子图连通的这个条件预处理即可)

    进一步优化,关于$j$和$T$的枚举可以分开,即先求出$g_{j}=min(f_{S,i}-len(i,j))$,再枚举包含$j$的$T$即可(这样做的实际意义是先将$S$中所有到$j$的边选择最小的),时间复杂度降为$o(n3^{n})$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 15
     4 struct ji{
     5     int nex,to,len;
     6 }edge[N*N];
     7 int E,n,m,x,y,z,head[N],vis[N],g[N],con[1<<N],sum[1<<N],f[1<<N][N];
     8 void add(int x,int y,int z){
     9     edge[E].nex=head[x];
    10     edge[E].to=y;
    11     edge[E].len=z;
    12     head[x]=E++;
    13 }
    14 void dfs(int k,int s){
    15     if (((s&(1<<k))==0)||(vis[k]))return;
    16     vis[k]=1;
    17     for(int i=head[k];i!=-1;i=edge[i].nex)dfs(edge[i].to,s);
    18 }
    19 int main(){
    20     scanf("%d%d",&n,&m);
    21     memset(head,-1,sizeof(head));
    22     for(int i=1;i<=m;i++){
    23         scanf("%d%d%d",&x,&y,&z);
    24         add(x-1,y-1,z);
    25         add(y-1,x-1,z);
    26     }
    27     memset(f,0x3f,sizeof(f));
    28     for(int i=0;i<(1<<n);i++){
    29         memset(vis,0,sizeof(vis));
    30         for(int j=0;j<n;j++)
    31             if (i&(1<<j)){
    32                 dfs(j,i);
    33                 break;
    34             }
    35         bool flag=0;
    36         for(int j=0;j<n;j++)
    37             if ((i&(1<<j))&&(!vis[j])){
    38                 flag=1;
    39                 break;
    40             }
    41         if (!flag){
    42             con[i]=1;
    43             if (i&1)f[i][0]=0;
    44         }
    45     }
    46     for(int i=1;i<(1<<n);i+=2){
    47         if (!con[i])continue;
    48         for(int x=0;x<n;x++){
    49             g[x]=0x3f3f3f3f;
    50             sum[(1<<x)]=0;
    51         }
    52         for(int x=0;x<n;x++)
    53             if ((i&(1<<x))){
    54                 for(int j=head[x];j!=-1;j=edge[j].nex){
    55                     y=edge[j].to;
    56                     if ((i&(1<<y))==0){
    57                         g[y]=min(g[y],f[i][x]-edge[j].len);
    58                         sum[(1<<y)]+=edge[j].len;
    59                     }
    60                 }
    61             }
    62         int ii=(1<<n)-1-i;
    63         for(int j=(ii&(ii-1));j>=0;j=((j-1)&ii)){
    64             int jj=(ii^j),k=(jj&(jj-1));
    65             sum[jj]=sum[jj^k]+sum[k];
    66             if (jj==ii)break;
    67         }
    68         for(int x=0;x<n;x++)
    69             for(int j=ii;j;j=((j-1)&ii))
    70                 if ((j&(1<<x))&&(con[j]))f[i|j][x]=min(f[i|j][x],g[x]+sum[j]);
    71     }
    72     printf("%d",f[(1<<n)-1][n-1]);
    73 }
    View Code
  • 相关阅读:
    应用层协议及ip地址划分
    请求与响应编码及jsp基本原理
    springboot注解
    springboot 快速入门
    Http协议简单解析及web请求过程
    Tomcat原理详解及请求过程
    mysql数据库乱码的问题解决
    AOP的实现原理
    Springl利用Aspectj的扩展实现Aop
    JDK动态代理实现原理
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14313468.html
Copyright © 2011-2022 走看看