問題
与えられた:問題の要約意味\(N- \)ポイント\(m個\)ようにエッジ単純無向グラフ(NO再ループフリー側)、コストは、現在の辺の数を削減しているが、\(1 \)\(N- \)だけの単純なパスは、コストを最小化しようとしています。
\(N \ 15、N-1 \ binom N2 \ \ \ M)
溶液
参照してください(nは当量15 \を\)\、おそらく複雑にされて推測することができます(O(3 ^ n)を\ \) またはそう、そして無駄に、迅速な解決をストレートスタイナー木を考えます。
状況が存在する必要があり、最終的な状況を考えるようになった\(1 \)する(N \)\パスを、そのパス上の2点を結ぶ他の経路が存在することができません。換言すれば、各点から開始し、その後わずかだけ経路上の点に到達することができ、非辺のパスを歩きます。
元の質問は、上記のアプローチに対応し、費用を消去する境界線の最小値を必要とすることを検討滞在を最大限にするために変換するために、右側を考えるのは簡単ですし、
絵は、おそらく各コレクション内の右側など、すべての側面よりも予約されている最大化することがハングいくつかのセット、および起因するものであるパスうなずき上の各点で言って、出てきました。
そして、DPを取得することは簡単です:セット([I] [S F \ ] \)は、パス(最終接続表します\(1 \)と\(N- \)パス)に行ってきました(私は\)\、および集合\(S \)既に前に掛け点、2つの転送があります。
- さらに、経路上:\(F [I]、[S] \ RIGHTARROW F [J] [S \カップ\ {J \}] \)であり、接続の重みを増加させる(I、Jの\)\右側に
- 電流設定点をぶら下げ:\(F [I]、[S] \ RIGHTARROW F [I] [S \カップT] \) 、設定値増加する権利\を(T \)側と、全ての右側
限り、前処理として\(G [S]が\)の集合を表し\(S \)側と右を、暴力を求めることができ、この工程の複雑\(O(2 ^ N-N ^ 2)\)
必要に(グローバルため、列挙サブセットの補数と列挙複雑同等のサブセット)の複雑転写のサブセットを列挙するとき、その後、転送\(O(N3 ^ N) \)
全体的な複雑性\(O(2 ^ N-N ^ 2 + N3 ^ N)\)
コード
#include <cstdio>
#define bin(x) (1<<(x))
#define b(x) (1<<(x)>>1)
inline void cmax(int&x, const int y) {x < y && (x = y);}
const int N = 17, M = 40100;
int f[N][M], g[M];
int mp[N][N];
int n, m;
int main() {
scanf("%d%d",&n,&m); int Ans = 0;
for(int i=1,x,y,z;i<=m;++i) {
scanf("%d%d%d",&x,&y,&z), Ans += z;
mp[x][y] = mp[y][x] = z;
}
for(int s=0;s<bin(n);++s) {
int&v = g[s];
for(int i=1;i<=n;++i) if(s & b(i))
for(int j=i+1;j<=n;++j) if(s & b(j)) v += mp[i][j];
}
for(int i=1;i<=n;++i)
for(int j=0;j<bin(n);++j)
f[i][j] = -1;
f[1][1] = 0;
for(int S=1;S<bin(n);++S)
for(int i=1;i<=n;++i) if((S & b(i)) and ~f[i][S]) {
for(int j=1;j<=n;++j) if((~S & b(j)) and mp[i][j]) cmax(f[j][S|b(j)], f[i][S] + mp[i][j]);
for(int iS=(bin(n)-1)^S, s = iS; s; s = (s-1) & iS)
cmax(f[i][S|s], f[i][S] + g[s|b(i)]);
}
printf("%d\n", Ans - f[n][bin(n)-1]);
return 0;
}