您的位置:首页 > 其它

SDOI 2006 - 保安站岗

2014-05-20 15:16 337 查看
最小监视覆盖,即选中费用最小的i个点来选中一些边,这些边把所有的点覆盖。

#include <cstdio>
using namespace std;

#define MAXV    1505
#define MAXE    (MAXV - 1)
int Vefw[MAXE], Veh[MAXV], Vet[MAXE], Vc[MAXV], Veptr;
int dp[MAXV][3],dp2[MAXV];

#define min(a,b) ((a)<(b)?(a):(b))

#define addedge(s,t)    do{\
Vefw[Veptr] = Veh[s], Vet[Veptr] = t;    \
Veh[s] = ++Veptr;}while(0)

void solve(int s)
{
dp[s][2] = 0, dp[s][1] = Vc[s];
for(int e = Veh[s]; e; e = Vefw[e]) {
int t = Vet[--e];
solve(t);
dp[s][1] += min(min(dp[t][0], dp[t][1]), dp[t][2]);
dp[s][2] += min(dp[t][0], dp[t][1]);
}
int k;
dp2[k=s] = 0x3f3f3f3f;
for(int e1 = Veh[s]; e1; e1 = Vefw[e1]) {
int t1 = Vet[--e1];
dp2[t1] = dp[t1][1];
for(int e2 = Veh[s]; e2; e2 = Vefw[e2]) {
int t2 = Vet[--e2];
if (t2 != t1) dp2[t1] += min(dp[t2][0], dp[t2][1]);
}
if (dp2[k] > dp2[t1]) k = t1;
}
dp[s][0] = dp2[k];
}

int N;

int main(void)
{
//    freopen("sdoi2006_guard.txt", "r", stdin);
scanf("%d", &N);
int root = 0;
for(int i=0; i<N; ++i) {
int s, k, c;
scanf("%d%d%d", &s, &k, &c);
Vc[--s] = k;
while(c) {
int t;
scanf("%d", &t); --t;
if (t == root) root = s;
addedge(s, t);
--c;
}
}
solve(root);
printf("%d\n", min(dp[root][0], dp[root][1]));
return 0;
}


1046
Accepted988
0
C++1421 B2014-05-20 14:36:41
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: