您的位置:首页 > Web前端

UVA-1218 Perfect Service

2015-12-08 21:35 423 查看
Brief description



Algorithm analyse

首先对这个题目分析。

首先想到的是类似前面的最大独立集,但这里是求最小独立集。

后来发现并不是。还是要好好分析。

学习别人的思想。

首先,对于任一节点。

1.该节点是服务器,其子节点可以是服务器也可以不是子服务器。dp[0]+=min(dp[v][0],dp[v][1]);

2.该节点不是服务器 a.其父亲是服务器,那么所有儿子不是服务器。dp[u][1]+=dp[v][2];

b.其父亲不是服务器,那么所有儿子中只有一个是服务器(这个要遍历),这里面有2个for循环是n^2的复杂度,不允许,可以根据前面已知的条件来。dp[u][1]是所有的不是子节点,减去]dp[v][2]加上dp[v][0] 就行了.

总体思路就出来了。但是实现时还是WR好久,也看了几个题解才做出来。

错误点

1.这是个无根树,但是我在建树的时候建立了方向(类似前面的题),这样就导致有的点被漏掉,然后就是无向图的实现我还是

好弱,看题解发现了2种方法,等等我都贴上来。

2.在for(int i=0;i<G[u].size();i++)的循环中

我直接dp[u][2]=min(dp[u][2],dp[v][0]-dp[v][2]+dp[u][1]);这导致了一个问题,我的dp[u][1]并没有全部加完。导致算出的 结果小。WR了n次。后来还是POJ上面的dis的测试数据发现的(ORZ,poj上面数据太弱,就是一个并查集。)

3.在结果的比较中,只需比较dp[][0]和dp[][2],因为没有父节点。

Code

LRJ的代码。

感觉LRJ的代码太繁琐了,但还是十分严谨,还是贴上来。

// UVa1218 Perfect Service
// Rujia Liu
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 10000 + 5;
const int INF = 1000000000;

vector<int> G[maxn], vertices;
int p[maxn], d[maxn][3];

// build a rooted tree and dfs sequence
void dfs(int u, int fa) {
vertices.push_back(u);
p[u] = fa;
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(v != fa) dfs(v, u);
}
}

int main() {
int n;
while(scanf("%d", &n) == 1) {
for(int i = 0; i < n; i++) G[i].clear();
for(int i = 0; i < n-1; i++) {
int u, v;
scanf("%d%d", &u, &v); u--; v--;
G[u].push_back(v);
G[v].push_back(u);
}
vertices.clear();
dfs(0, -1);
for(int i = vertices.size()-1; i >= 0; i--) {
int u = vertices[i];
d[u][0] = 1; d[u][1] = 0;
for(int j = 0; j < G[u].size(); j++) {
int v = G[u][j];
if(v == p[u]) continue;
d[u][0] += min(d[v][0], d[v][1]); // u is server
d[u][1] += d[v][2]; // u is not server, u's father is server
if(d[u][0] > INF) d[u][0] = INF; // avoid overflow!
if(d[u][1] > INF) d[u][1] = INF;
}
d[u][2] = INF;
for(int j = 0; j < G[u].size(); j++) {
int v = G[u][j];
if(v == p[u]) continue;
d[u][2] = min(d[u][2], d[u][1] - d[v][2] + d[v][0]); // neither u or father is server
}
}
printf("%d\n", min(d[0][0], d[0][2]));
scanf("%d", &n); // flag
}
return 0;
}
然后是链表实现无向图的。

以前我总是对这个存在畏惧感,但是,一点都不难。现在再看,很好理解!相信自己。

对于nxt的理解。

[u]这是为了以后for循环中的遍历,到-1停止.


参考代码



#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-10)
#define INF 1e6
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=11000;

struct Edge
{
int to;
int nxt;
}edge[maxn*2];

int Adj[maxn],Size;
int dp[maxn][3],n;

void init()
{
Size=0;
for(int i=0;i<n+10;i++)
{
Adj[i]=-1;
dp[i][0]=1;
dp[i][1]=0;
dp[i][2]=INF;
}
}

void add_edge(int u,int v)
{
edge[Size].to=v;
edge[Size].nxt=Adj[u];
Adj[u]=Size++;
}

void dfs(int u,int fa)
{
for(int i=Adj[u];~i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa) continue;
dfs(v,u);
dp[u][0]+=min(dp[v][0],dp[v][1]);
dp[u][1]+=dp[v][2];
dp[u][2]=min(dp[u][2],dp[v][0]-dp[v][2]);
}
dp[u][2]+=dp[u][1];
}

int main()
{
while(~scanf("%d",&n))
{
if(n==-1) break;
else if(n==0) continue;
init();
for(int i=0;i<n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add_edge(a,b);
add_edge(b,a);
}
dfs(1,0);
printf("%d\n",min(dp[1][0],dp[1][2]));
}
return 0;
}
vector

#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-10)
#define INF 1e6
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=10010;
int dp[maxn][3];
int n,root;
vector<int> G[maxn];

void init(int t)
{
for(int i=0;i<t+10;i++)
G[i].clear();
for(int i=0;i<t+10;i++)
{
dp[i][0]=1;
dp[i][1]=0;
dp[i][2]=INF;
}
}

void dfs(int u,int fa)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa) continue;
dfs(v,u);
dp[u][0]+=min(dp[v][0],dp[v][1]);
dp[u][1]+=dp[v][2];
dp[u][2]=min(dp[u][2],dp[v][0]-dp[v][2]);
}
dp[u][2]+=dp[u][1];
}

int main()
{
while(~scanf("%d",&n))
{
if(n==-1) break;
if(n==0)  continue;
init(n);
int a,b;
n--;
while(n--)
{
scanf("%d%d",&a,&b);
G[a].pb(b);
G[b].pb(a);
}
dfs(1,0);
printf("%d\n",min(dp[1][0],dp[1][2]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: