Enumerates all sides, divides the tree into two trees, and asks for the minimum amount of change for the two numbers.
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace Std;
const int MAXN = 3030;
const int inf = 0X7FFFFFFF;
int DP[MAXN];
struct Edge
{
int flag, V;
int u;
int next;
}EDGE[2*MAXN];
int HEAD[MAXN];
int VIS[MAXN];
int Nedge;
int mi;
Int St;
int num;
void Addedge (int u, int v)
{
edge[nedge].u = u;
EDGE[NEDGE].V = v;
Edge[nedge].flag = 1;
Edge[nedge].next = Head[u];
Head[u] = nedge++;
edge[nedge].u = v;
EDGE[NEDGE].V = u;
Edge[nedge].flag = 0;
Edge[nedge].next = Head[v];
HEAD[V] = nedge++;
}
void Init ()
{
int Nedge = 0;
memset (Vis, 0, sizeof (VIS));
Memset (Head,-1, sizeof (head));
memset (DP, 0, sizeof (DP));
}
void Dfs (int u)
{
Vis[u] = 1;
for (int i = head[u]; I! =-1; i = edge[i].next)
{
if (num = = i) continue;
int v = EDGE[I].V;
if (Vis[v]) continue;
if (Edge[i].flag = = 0)
dp[u]++;
DFS (v);
DP[U]+=DP[V];
}
}
void dfs_s (int u, int sum_1, int sum_0)
{
Vis[u] = 1;
mi = min (dp[u] = (Dp[st]-sum_0 + sum_1), MI);
for (int i = head[u]; I! = -1;i = Edge[i].next)
{
if (num = = i) continue;
int v = EDGE[I].V;
if (Vis[v]) continue;
if (Edge[i].flag = = 0) dfs_s (V, sum_1, sum_0 + 1);
else if (Edge[i].flag = = 1) dfs_s (V, sum_1 + 1, sum_0);
}
}
int main ()
{
Freopen ("Input.txt", "R", stdin);
int n;
while (~SCANF ("%d", &n))
{
int u, v;
Init ();
for (int i = 1;i < n;i++)
{
scanf ("%d%d", &u, &v);
Addedge (U, v);
}
int ans = inf;
int t = 0;
for (int i = 0;i < nedge;i++)
{
mi = inf;num = i;st = edge[i].u;
memset (Vis, 0, sizeof (VIS));
memset (DP, 0, sizeof (DP));
DFS (EDGE[I].U);
memset (Vis, 0, sizeof (VIS));
dfs_s (edge[i].u, 0, 0);
T + = mi;
if (i&1) ans = min (ans, t), t = 0;
}
if (ans = = inf) puts ("0");
else printf ("%d\n", ans);
}
return 0;
}
Codeforces Round #148 (Div. 1) C-Tree DP