• 精简改良(生成树dp)


    精简改良

       

    0.00%

    提交人数:1

    通过人数:0

    题目描述

     

    可怜最近在玩一款硬核战争游戏。

    可怜控制的国家有 nn 座城市,在 nn 座城市之间有 mm 条双向道路,第 ii 条道路连接了城市 u_iui 和 v_ivi,且通过这条道路的时间为 w_iwi

    最近,可怜点了名为"传送"的科技,这个科技可以让可怜的士兵能在国家的任意两个城市之间不经过道路快速地传送。这样从战争的角度来说,道路几乎就没有用了,可怜希望能删除一些道路,使得道路系统尽可能地不便,这样在敌人入侵时就能获得优势。

    游戏的规则规定在任何时刻,同一个国家的任意两个城市之间都必须要能通过道路到达。因此可怜需要保证在删除道路之后,道路系统仍然是联通的。

    令 d(i,j)d(i,j) 为通过道路系统从第 ii 个城市到第 jj 个系统的最短时间,可怜定义一个道路系统的复杂度为 sum_{i=1}^n sum_{j=i+1}^n d(i,j)i=1nj=i+1nd(i,j)。可怜希望能删除一些道路,在保证图联通的情况下,使道路系统的复杂度尽可能的大。

     

     
     

    输入描述

     

    一行输入两个整数 n,m(1 leq n leq 14, 1 leq m leq frac{n(n-1)}{2})n,m(1n14,1m2n(n1)),表示城市数量与初始的道路数量。

    接下来 mm 行每行输入三个整数 u_i,v_i,w_i(1 leq u_i,v_i leq n, 1 leq w_i leq 10^9)ui,vi,wi(1ui,vin,1wi109),描述了一条道路。

    输入保证图中没有自环、重边,同时图是联通的。

     

    输出描述

     

    输出一行一个整数,表示道路系统最大的可能的复杂度。

     

    样例输入 1 

    5 5
    1 2 1
    1 3 1
    2 4 1
    2 5 1
    1 5 1

    样例输出 1

    20

    样例输入 2 

    5 10
    1 2 1
    1 3 2
    1 4 3
    1 5 4
    2 3 5
    2 4 6
    2 5 7
    3 4 8
    3 5 9
    4 5 10

    样例输出 2

    146




    生成树dp 套路
    dp[s][i] 集合 s,以i为树根的 什么什么东西
    两个集合合并的时候考虑连接两个集的边
    然后用到了子集的遍历




    
    
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define INFLL 0x3f3f3f3f3f3f3f3f
     6 #define N 110
     7 int n, m;
     8 int dist[20][20];
     9 ll f[1 << 15][15];
    10 
    11 vector <int> vec[1 << 15];
    12 int sze[1 << 15];
    13 
    14 int main()
    15 {
    16     while (scanf("%d%d", &n, &m) != EOF)
    17     {
    18         memset(dist, -1, sizeof dist); 
    19         memset(f, -1, sizeof f);
    20         for (int S = 0, len = (1 << n); S < len; ++S) 
    21         {
    22             for (int i = 0; i < n; ++i) if ((S >> i) & 1)
    23                 vec[S].push_back(i + 1); 
    24             sze[S] = vec[S].size();
    25             if (sze[S] == 1)
    26                 f[S][*vec[S].begin()] = 0; 
    27         }    
    28         for (int i = 1, u, v, w; i <= m; ++i)
    29         {
    30             scanf("%d%d%d", &u, &v, &w);
    31             dist[u][v] = dist[v][u] = w; 
    32         }
    33         ll res = 0;  
    34         for (int S = 1, len = (1 << n); S < len; ++S)
    35         {  
    36             for (auto u : vec[S])
    37             {
    38                 for (int T = (S - 1) & S; T != 0; T = (T - 1) & S) // 枚举子集  
    39                 {
    40                     for (auto v : vec[T])
    41                     {
    42                         if (dist[u][v] == -1 || f[T][v] == -1 || f[S - T][u] == -1) continue;   
    43                         f[S][u] = max(f[S][u], f[T][v] + f[S - T][u] + 1ll * dist[u][v] * sze[T] * (n - sze[T]));  
    44                     }
    45                 }
    46                 if (S == (1 << n) - 1)res = max(res, f[S][u]);
    47             }
    48         }
    49         printf("%lld
    ", res);
    50     }
    51     return 0;
    52 }







  • 相关阅读:
    深入理解Java内存模型(JMM)
    Java基础知识①
    Java自旋锁的几种实现
    ConcurrentHashMap的CAS操作
    Java集合对比总结
    python模块--os模块
    python模块--random
    Datafactory 学习笔记
    Datafactory 实际使用案例
    Oracle三种排名函数使用
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10956909.html
Copyright © 2020-2023  润新知