码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5290 Bombing plan

时间:2015-07-27 18:59:22      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:

题意
X国有n(n<105)个城市,用n-1条无向边连接。城市i有一个权值wi(wi<100),如果炸毁城市i,那么距离i不超过wi的节点也会被炸毁。求炸毁所有城市最少需要炸几次。
Solution
相比前几天做的SGU 280 不同之处在与这题对每个点有不同的k。 
但这一题不能贪心,只能采用dp的方法。形式上却也差不多,都是对子树的讨论。令f[i][j]为以i为根的子树,能向子树外拓展i个节点最少需要炸毁几个城市。G[i][j]为以i为根的子树,子树内有节点未被炸毁,且距离根为j最少需要炸毁几个城市。 
转移方程: 
不炸毁u点 
f[u][j]=f[v][j+1]+min(f[k][0 j+1],G[k][0 j])
G[u][0]=f[u][0]
G[u][j]=G[v][j?1]+min(f[k][0 j?1],G[k][0 j?1])
炸毁u点 
f[u][w[u]]=1+min(f[v][0 w[u]+1],G[v][w[u]])
这里需要对f[][]和G[][],求前缀最小值。 
节点比较多,避免爆栈不能直接用递归的方法做。 
时间复杂度On?w技术分享

Bombing plan

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 364    Accepted Submission(s): 86


Problem Description
Kingdom Y is in the war with kingdom X. Kingdom X consists of N cities,there are N-1 bidirectional roads which are all 1 long ,each of them connect a pair of cities,the N cities are all connect by the N-1 bidirectional.People can travel through the roads.

Now kingdom Y is going to bomb kingdom X. Every city of kingdom X has its own value W. If city i was to be bombed, then all the cities that lie within the distance W(i) from city i would be destroyed as well. The king of kingdom Y wants to know the minimum bombing time that can destroy all the cities in kingdom X. Could you help him?
 

Input
There are multiple test cases. Please process till EOF.
In each test case: 
First line: an integer n(n<=10^5) indicating the number of city
Second line:contain n numbers w[i](0<=w[i]<=100) ,indicating that the value of city[i],
Next n - 1 lines: each contains two numbers ui and vi, (1 ≤ ui,vi<=n), indicates that there’s one road connecting city ui and vi.

 

Output
For each case,output one number, denotes the minimum number of bombing times.
 

Sample Input
5 1 1 1 1 1 1 2 2 3 3 4 4 5
 

Sample Output
2
 

Author
FZUACM
 

Source
 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define prt(k) cout<<#k" = "<<k<<endl;
const int inf = 0x3f3f3f3f;
const int N = 100007;
const int W = 107;
int f[N][107], g[N][107];
int father[N];
int n;
int w[N];
int F[N][107], G[N][107];
int maxw;
struct edge
{
        int v, next;
}e[N<<1];
int head[N], mm;
void add(int u,  int v)
{
        e[mm].v = v;
        e[mm].next = head[u];
        head[u] = mm++;
}
struct P
{
        int d, id;
        P() {}
        P(int _id, int _d=0) { d=_d, id=_id; }
        bool operator < (P b) const
        {
                return d > b.d;
        }
}p[N];
bool vis[N];
void bfs()
{
        queue<P> q;
        q.push(P(1,0));
        memset(vis,0,sizeof vis);
        vis[1] = true;
        father[1] = 1;
        while (!q.empty()) {
                P u = q.front(); q.pop();
                int now = u.id;
                p[now].id = now;
                p[now].d = u.d + 1;
                for (int i=head[now];~i;i=e[i].next) {
                        int v = e[i].v;
                        if (!vis[v]) {
                                q.push(P(v, u.d + 1));
                                vis[v] = true;
                                father[v] = now;
                        }
                }
        }
}
void gao(int u, int fa)
{
        assert(!vis[u]);
        vis[u] = true;
        bool flag = false;
        for (int i=head[u];~i;i=e[i].next) {
                int v = e[i].v;
                if (v==fa) continue;
                flag = true;
                assert(vis[v]);
        }
        if (!flag) {
                g[u][0] = 0;
                f[u][w[u]] = 1;
        }
        for (int j=0;j<=maxw;j++) {
                ll sum=0;
                for (int i=head[u];~i;i=e[i].next) {
                        int v = e[i].v;
                        if (v==fa) continue;
                        int t = F[v][j+1];
                        if (j > 0)
                                t = min(t, G[v][j-1]);
                        sum += t;
                        if (sum >= inf) { sum = inf; break; }
                }
                if (sum < inf ) for (int i=head[u];~i;i=e[i].next) {
                        int v = e[i].v;
                        if (v==fa) continue;
                        int t = F[v][j+1];
                        if (j > 0) t = min(t, G[v][j-1]);
                        if (0<=sum && sum < inf) f[u][j] = min(f[u][j], (int)(f[v][j+1] + sum - t ) ) ;
                }
                sum = 0;
                int t;
                for (int i=head[u];~i;i=e[i].next) {
                        int v = e[i].v;
                        if (v==fa) continue;
                        int t = F[v][j];
                        if (j > 0) t = min(t, G[v][j-1]);
                        sum += t;
                        if (sum >= inf)  { sum = inf; break; }
                }
                if (j>0 && sum < inf) for (int i=head[u];~i;i=e[i].next) {
                        int v = e[i].v;
                        if (v==fa) continue;
                        int t = F[v][j];
                        if (j > 0) t = min(t, G[v][j-1]);
                        if (0<=sum && sum < inf) g[u][j]=min(g[u][j], (int)(g[v][j-1] + sum -  t ) );
                }
        }
        ll sum = 0;
        for (int i=head[u];~i;i=e[i].next) {
                int v = e[i].v;
                if (v==fa) continue;
                sum += min(F[v][w[u]+1], w[u]>0 ? G[v][w[u]-1] : inf);
        }
        if (0<=sum && sum<inf) f[u][w[u]]=min(f[u][w[u]], int(1 +  sum ));
        F[u][0] = f[u][0];
        G[u][0] = g[u][0];
        for (int j=1;j<=maxw+1;j++) {
                F[u][j] = min(F[u][j-1], f[u][j]);
                G[u][j] = min(G[u][j-1], g[u][j]);
        }
}
int main()
{
        while (scanf("%d", &n)==1) {
                maxw = 0;
                for (int i=1;i<=n;i++) scanf("%d", w+i), maxw=max(maxw, w[i]);
                mm=0; memset(head,-1,sizeof head);
                for (int i=1;i<=n-1;i++)
                {
                        int u, v; scanf("%d%d", &u, &v);
                        add(u, v);
                        add(v, u);
                }
                memset(f, 63, sizeof f);
                memset(g, 63, sizeof g);
                bfs();
                sort(p+1, p+n+1);
                memset(vis, 0, sizeof vis);
                for (int i=1;i<=n;i++) {
                        gao(p[i].id, father[p[i].id]);
                }
                int ans = n;
                for (int i=0;i<=maxw;i++)
                        ans =  min(ans, f[1][i]);
                printf("%d\n", ans);
        }
}
/**
3
1 1 1
1 2
2 3
7
1 1 1 1 1 1 1
1 2
2 3
3 4
4 5
5 6
6 7
4
0 1 0 1
1 2
1 3
1 4
4
0 2 0 0
1 2
1 3
1 4

*/


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 5290 Bombing plan

标签:

原文地址:http://blog.csdn.net/oilover/article/details/47087655

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!