Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 1294 Accepted: 669
Country Z has N cities, which are numbered from 1 to N. Cities are connected by highways, and there is exact one path between two different cities. Recently country Z often caught fire, so the government decided to build some firehouses in some cities. Build a firehouse in city K cost W(K). W for different cities may be different. If there is not firehouse in city K, the distance between it and the nearest city which has a firehouse, can’t be more than D(K). D for different cities also may be different. To save money, the government wants you to calculate the minimum cost to build firehouses.
The first line of input contains a single integer T representing the number of test cases. The following T blocks each represents a test case.
The first line of each block contains an integer N (1 < N <= 1000). The second line contains N numbers separated by one or more blanks. The I-th number means W(I) (0 < W(I) <= 10000). The third line contains N numbers separated by one or more blanks. The I-th number means D(I) (0 <= D(I) <= 10000). The following N-1 lines each contains three integers u, v, L (1 <= u, v <= N,0 < L <= 1000), which means there is a highway between city u and v of length L.
For each test case output the minimum cost on a single line.
5
5
1 1 1 1 1
1 1 1 1 1
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 1 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 3 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
4
2 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
4
4 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
2
1
2
2
3
POJ Monthly,Lou Tiancheng
给一棵带权树,每个节点需要被覆盖,覆盖节点i的方法为一下二者之一:
求覆盖整棵树的最小代价
记dp[i][j]表示第i号节点被j号节点覆盖,且i号节点的子树被全部覆盖的最小代价,best[i]表示将i号节点的子树全部覆盖的最小代价,dis[i][j]表示树上两点i,j间的距离
dis[i][j]可以用 O(n2) 的时间预处理
dp[i][j]和best[i]可以这样转移
/*
POJ2152
Author:Johann
*/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
inline int read() {
char c = getchar(); int x = 0;
while(!isdigit(c)) c = getchar();
while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
return x;
}
const int N = 1500;
const int inf = 1000000000;
struct edge{
int from, to, len, nxt;
}e[N * 2];
int dp[N][N], dis[N][N];
int head[N], best[N], vis[N], w[N], d[N], lst[N];
int q[N];
int T, n, tail = 0, cnt = 0;
void addedge(int x, int y, int z) {
e[++tail].from = x;
e[tail].to = y;
e[tail].len = z;
e[tail].nxt = head[x];
head[x] = tail;
}
void work(int root) {
if (root == 1) lst[cnt = 1] = 1;
memset(vis, 0, sizeof(vis));
dis[root][root] = 0;
vis[root] = 1;
int l = 1, r = 1;
q[1] = root;
while(l <= r) {
int x = q[l]; l++;
for(int i = head[x]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if (!vis[v]) {
vis[v] = 1;
if (root == 1) lst[++cnt] = v;
dis[root][v] = dis[root][x] + e[i].len;
q[++r] = v;
}
}
}
}
void DP() {
memset(vis, 0, sizeof(vis));
red(k, n, 1) {
int u = lst[k];
vis[u] = 1;
best[u] = inf;
rep(j, 1, n) {
if (dis[u][j] > d[u]) {
dp[u][j] = inf;
continue;
}
dp[u][j] = 0;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if (!vis[v]) continue;
dp[u][j] += min(dp[v][j] - w[j], best[v]);
}
dp[u][j] += w[j];
if (dp[u][j] < best[u]) best[u] = dp[u][j];
}
}
}
int main() {
scanf("%d", &T);
while(T--) {
tail = 0;
n = read();
rep(i, 1, n) w[i] = read();
rep(i, 1, n) d[i] = read();
rep(i, 1, n) head[i] = -1;
rep(i, 1, n - 1) {
int x = read(), y = read(), z = read();
addedge(x, y, z);
addedge(y, x, z);
}
rep(i, 1, n) work(i);
DP();
printf("%d\n", best[1]);
}
return 0;
}
终于拿到新键盘了,写题的动力!
茶轴真棒!
千万不能把Codeforces的习惯带入POJ(可见BZOJ的优越),第一次体会到STL Queue被卡T的快感
陈启峰论文题……好吧的确不容易
老大在机房里开了监!控!
监!控!
重复一遍,HBH是心机婊