UVa-1218 - Perfect Service

d[u][0][1]=sum{d[v][0]}

d[u][1][1]=d[u][1][0]=sum{min(d[v][0],d[v][1])}

d[u][0][0]=sum{d[v][0]}-d[min][0]+d[min][1]   (d[min][1]=min(d[v][1]))

调了很久。。。。 看到lrj是先dfs找好路径,再反方向沿着路径递推。O(n)。

最近效率低下!

谁笑到最后谁笑得最好!

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<vector>
 5 #define pb push_back
 6 using namespace std;
 7 const int inf=1e4;
 8 const int maxn=10010;
 9 int n;
10 vector<int> vt[maxn];
11 int d[maxn][2][2];
12 int dp(int u,int p,int f,int fa)//父节点是fa,父节点的决策f,当前结点的决策p,当前结点u
13 {
14     int &ans=d[u][p][f];
15     if(vt[u].empty()) return 1;
16     if(vt[u].size()==1&&vt[u][0]==fa) return ans=((!p&&!f)?inf:p);
17     if(ans>-1) return ans;
18     ans=p;
19     int mn=inf;
20     for(int i=0;i<vt[u].size();i++)
21     {
22         int v=vt[u][i];
23         if(v==fa) continue;
24         if(p)
25         {
26             int d1=dp(v,0,p,u);
27             int d2=dp(v,1,p,u);
28             ans+=min(d1,d2);
29         }
30         else if(f) ans+=dp(v,0,p,u);
31         else
32         {
33             ans+=dp(v,0,p,u);
34             mn=min(mn,dp(v,1,p,u)-d[v][0][p]);
35         }
36     }
37     if(!p&&!f) ans+=mn;
38     return ans;
39 }
40 int main()
41 {
42     while(scanf("%d",&n)&&n>-1)
43     {
44         if(n==0) scanf("%d",&n);
45         for(int i=1;i<=n;i++) vt[i].clear();
46         memset(d,-1,sizeof(d));
47         for(int i=1;i<=n-1;i++)
48         {
49             int u,v;
50             scanf("%d%d",&u,&v);
51             vt[u].pb(v);
52             vt[v].pb(u);
53         }
54         printf("%d\n",min(dp(1,0,0,0),dp(1,1,0,0)));
55     }
56 }
时间: 2024-11-08 20:13:45

UVa-1218 - Perfect Service的相关文章

UVA - 1218 Perfect Service(树形dp)

题目链接:id=36043">UVA - 1218 Perfect Service 题意 有n台电脑.互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连接且仅仅能连接一台server(不包含作为server的电脑).求最少须要多少台电脑作为server. 思路 典型的树形dp问题,那么我们来建立模型. d(u,0):u是server,孩子是不是server均可 d(u,1):u不是server,u的父亲是server,u的孩子不能是server d(u,2)

POJ 3398 / UVA 1218 Perfect Service 树形DP

树形DP Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1378   Accepted: 668 Description A network is composed of N computers connected by N ? 1 communication links such that any two computers can be communicated via a uniqu

Perfect Service UVA - 1218(树形dp)

Perfect Service UVA - 1218 题意:安装服务器,使得不是服务器的计算机恰好和一台服务器计算机相连.问最少安多少服务器计算机. 之前一直不理解第三个转移方程,,今天再看竟然是错的!!可是却过了!! 下面的是改过的了. 1 #include <cstdio> 2 #include <bits/stdc++.h> 3 using namespace std; 4 const int maxn=10010; 5 int d[maxn][3]; 6 int in[ma

UVA 10622 - Perfect P-th Powers(数论)

UVA 10622 - Perfect P-th Powers 题目链接 题意:求n转化为b^p最大的p值 思路:对n分解质因子,然后取所有质因子个数的gcd就是答案,但是这题有个坑啊,就是输入的可以是负数,负数的情况比较特殊,p只能为奇数,这时候是要把答案不断除2除到为奇数即可. 代码: #include <stdio.h> #include <string.h> #include <math.h> long long n; int prime[333333], vi

UVa 1218 完美的服务

https://vjudge.net/problem/UVA-1218 题意: 有n台机器形成树状结构.要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻.求服务器的最少数量. 思路: 和紫书上前面的UVa1220挺像的,不过这题是一棵无根树,就把0当做根就行了,方法还是一样的dfs. d[u][0]:u是服务器,则每个子结点可以是服务器也可以不是. d[u][1]:u不是服务器,但u的父亲是服务器,这意味着u的所有子结点都不是服务器. d[u][2]:u和u的

uva1218 Perfect Service

题目大意: 有n(n≤10000)台机器形成树形结构.要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻.求服务器的最少数量. /* 递归时分为3种情况 0表示,u为服务器,那么他的所有子节点可以为服务器也可以不为服务器 res+=min(dp[v][0],dp[v][1]); 1表示,u不为服务器,但是u的父节点为服务器,那么所有子节点都不能为服务器 res=sum(dp[v][2]); 2表示,u不为服务器,且u的父亲也不为服务器,那么u的子节点中只有一个为

UVA 10622 Perfect P-th Powers

https://vjudge.net/problem/UVA-10622 将n分解质因数,指数的gcd就是答案 如果n是负数,将答案除2至奇数 原理:(a*b)^p=a^p*b^p #include<cmath> #include<cstdio> #include<algorithm> #define N 65550 using namespace std; int gcd(int a,int b) { return !b ? a : gcd(b,a%b); } int

UVA1218 Perfect Service(染色问题--树形DP)(好题,通法)

题意:一棵树,进行染色,每个没染色的节点恰好和一个染色的节点相连,求染色的节点最少的个数X(以下均以X代表子问题的解) 思路:树形DP,细化状态,从而对每个节点的每种状态互相递推 这里如何细化状态是难点,而且也是这类难题的共同问题 很容易知道每个节点i至少两个状态:dp[i][0]: i没染上色时以i的子树的X.dp[i][1]: i被染色以i为子树的X 但是仅仅这两个状态无法实现状态转移因为: dp[u][0]=sum(dp[v][0],dp[v][1])+1  (dp[u][0]可以找到状态

UVa 10622 - Perfect P-th Powers(数论)

#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using namespace std; int find(int n) { for (int i = 2 ; i < 50000 ; ++ i) { if (pow(0.0+i, (int)(log10