码迷,mamicode.com
首页 > 其他好文 > 详细

精简改良(生成树dp)

时间:2019-05-31 19:30:20      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:contain   因此   sizeof   continue   有用   size   strong   header   输出   

精简改良

   

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=1n?j=i+1n?d(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?,vi?n,1wi?109),描述了一条道路。

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

 

输出描述

 

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

 

样例输入 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\n", res);
50     }
51     return 0;
52 }

 








 

精简改良(生成树dp)

标签:contain   因此   sizeof   continue   有用   size   strong   header   输出   

原文地址:https://www.cnblogs.com/zhangbuang/p/10956909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!