説明
ツリーは右側がエッジを有する、があります。
木があり、\(k個\)を泥棒移動速度が正の無限大、最初は警察です\(S \)の位置、移動速度の\(1 \) 、すべての泥棒(泥棒と警察をキャッチするための時間の最小量を見つけます最適な意思決定、できるだけ長く泥棒)。
\(N \ 50 \)
溶液
このタイトルのデータ範囲を参照してください非常に小さいので、我々は、高次元のDPを考えます。
セット\(DP [P] [uは ] [S_1] [S_2] \) から調製された警察のパフォーマンス\(のp \)が行ってきました\(U \)をサブツリーが直面しているが、持っている\(S_1を\)泥棒、他の人には、\(S_2 \)泥棒、泥棒と最小時間のすべてをキャッチします。
そして、あなたは直接サブツリーに残し、そして沈没サブツリーに行き、木のバックパックが転送を行う、国境に注意を払うどのように多くの泥棒列挙することができます:
- \(S_1が\)する(0 \)\ \、(S_2 \)する(0 \)\、タスクは、ゼロまでの時間を完了する。
- \(S_1 \)する(0 \)\ \、(S_2 \)されていません(0 \)\、このステップは、割り当てられた、意味がありません\(INF \)を。
uは、リーフノードであり、S1点は、\(DP [P] [U ] [S_1] [S_2] \ LEFTARROW DP [U] [P] [S_2] [0] + edgeval(U、V)\) 、キャッチ\(S_1 \)個人の後に戻ります。
コード
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>
typedef long long LL;
typedef unsigned long long uLL;
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define MP(x, y) std::make_pair(x, y)
#define DE(x) cerr << x << endl;
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO cerr << "GO" << endl;
#define rep(i, a, b) for (register int (i) = (a); (i) <= (b); ++(i))
using namespace std;
inline void proc_status()
{
ifstream t("/proc/self/status");
cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
}
inline int read()
{
register int x = 0; register int f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
return x * f;
}
template<class T> inline void write(T x)
{
static char stk[30]; static int top = 0;
if (x < 0) { x = -x, putchar('-'); }
while (stk[++top] = x % 10 xor 48, x /= 10, x);
while (putchar(stk[top--]), top);
}
template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
const int maxN = 50;
int n, m, police;
vector<int> g[maxN + 1];
int edge[maxN + 1][maxN + 1], size[maxN + 1], deg[maxN + 2];
int dp[maxN + 1][maxN + 1][maxN + 1][maxN + 1];
void link(int u, int v, int w)
{
deg[u]++;
g[u].push_back(v);
edge[u][v] = w;
}
void Input()
{
n = read();
for (int i = 1; i < n; ++i)
{
int u = read(), v = read(), w = read();
link(u, v, w), link(v, u, w);
}
police = read();
m = read();
for (int i = 1; i <= m; ++i) size[read()]++;
}
void dfs(int u, int fa)
{
for (int v : g[u])
if (v != fa)
dfs(v, u), size[u] += size[v];
}
int DP(int p, int u, int s1, int s2)
{
if (!s1 and !s2) return 0;
if (!s1) return 0x3f3f3f3f;
if (dp[p][u][s1][s2] != -1) return dp[p][u][s1][s2];
if (deg[u] == 1) return dp[p][u][s1][s2] = DP(u, p, s2, 0) + edge[p][u];
int tmp[maxN + 2];
memset(tmp, 0, sizeof tmp);
tmp[0] = 0x3f3f3f3f;
for (int v : g[u])
if (v != p)
{
for (int i = s1; i >= 0; --i)
for (int j = 0; j <= i; ++j)
chkmax(tmp[i], min(tmp[i - j], DP(u, v, j, s1 + s2 - j)));
}
return dp[p][u][s1][s2] = tmp[s1] + edge[p][u];
}
void Solve()
{
memset(dp, -1, sizeof dp);
dfs(police, 0);
int ans = 0x3f3f3f3f;
for (int v : g[police])
chkmin(ans, DP(police, v, size[v], m - size[v]));
printf("%d\n", ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("CF868E.in", "r", stdin);
freopen("CF868E.out", "w", stdout);
#endif
Input();
Solve();
return 0;
}