您的位置:首页 > 其它

uva 10859 Placing Lampposts / Tree DP

2013-02-19 13:14 330 查看
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&page=show_problem&problem=1800

  树DP,要求求出最小覆盖点集,并且要求两端都有覆盖的边尽可能多。于是,这题可以通过赋权,求树的最小权值。无向无环图通过dfs变成有根树一棵,然后对每个树根DP,最后得到答案。

代码如下:

View Code

#define REP(i, n) for (int i = 0; i < (n); i++)

int dp[2]
;
bool vis
;
VI rel
;

void input(int n, int m) {
REP(i, n) {
rel[i].clear();
vis[i] = false;
}
int u, v;
REP(i, m) {
cin >> u >> v;
rel[u].PB(v);
rel[v].PB(u);
}
}

void dfs(int x) {
vis[x] = true;
dp[0][x] = 0;
dp[1][x] = 1 << 12;
REP(i, SZ(rel[x])) {
int t = rel[x][i];
if (!vis[t]) {
dfs(t);
dp[0][x] += dp[1][t] + 1;
if (dp[0][t] < dp[1][t]) dp[1][x] += dp[0][t] + 1;
else dp[1][x] += dp[1][t];
}
}
//    cout << x << " :";
//    REP(i, SZ(rel[x])) cout << rel[x][i] << ends;
//    cout << endl;
//    cout << x << ends << dp[0][x] << ends << dp[1][x] << endl;
}

int work(int n) {
_clr(vis);
int ret = 0;
REP(i, n) {
if (!vis[i]) {
dfs(i);
ret += min(dp[0][i], dp[1][i]);
}
}
return ret;
}

int main() {
//    freopen("in", "r", stdin);
int T, n, m;
while (cin >> T) {
while (T--) {
cin >> n >> m;
input(n, m);
int ans = work(n);
cout << (ans >> 12) << ' ' << m - (ans & 0x00000FFF) << ' ' << (ans & 0x00000FFF) << endl;
}
}
return 0;
}


——written by Lyon
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: