精简改良(生成树dp)
尚未提交?尚未通過?時間限制:2000ms?內存限制:256MB
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(1≤n≤14,1≤m≤2n(n?1)?),表示城市數量與初始的道路數量。
接下來?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?(1≤ui?,vi?≤n,1≤wi?≤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 }
?
?
轉載于:https://www.cnblogs.com/zhangbuang/p/10956909.html
總結
以上是生活随笔為你收集整理的精简改良(生成树dp)的全部內容,希望文章能夠幫你解決所遇到的問題。