uva 10859 放置街灯--Placing Lampposts

uva 10859 - Placing Lampposts(树形dp

###两个别人家的代码,没有注释看了很久
###所以自己改写了一遍,附注释

https://blog.csdn.net/keshuai19940722/article/details/19363649
https://blog.csdn.net/deepquiet/article/details/50609020

//:page70(刘汝佳算法竞赛入门经典--训练指南)
//树形递归

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<memory.h>

using namespace std;

const int M = 2000;//每开一个灯就加M
const int N = 1010;

int n,m;//点数和m行数据
int v[N];
int dp[N][2];//dp[i][j]以i为根节点的状态是j的最小X j=0 or 1(on/off)
vector<int> g[N];//邻接矩阵

void init()		//数据初始化
{
	scanf("%d%d",&n,&m);
	
	for(int i = 0;i < n;i++) g[i].clear(); //清空数据,每次重新输入后
	memset(v,0,sizeof(v));
	memset(dp,0,sizeof(dp));
	
	for(int i = 0;i < m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);//无向图 初始化邻接表
		g[a].push_back(b);
		g[b].push_back(a);
	}
}

void dfs(int x)//深搜遍历整棵树 以x为顶点  0<x<n-1 
{
	//根节点预处理
	v[x] = 1;  //表明这个点已经遍历过
	dp[x][0] = 0;//顶点不开灯为0
	dp[x][1] = M;//开灯为M
	//子节点
	for(int i = 0;i < g[x].size();i++)//遍历邻接表
	{
		int u =g[x][i];//与X相邻的点
		if(v[u]) continue; //防止重复遍历
		dfs(u);//深搜继续遍历下一个
		dp[x][0] += dp[u][1] + 1;//父节点不放灯的情况,子节点放灯
		if(dp[u][1] > dp[u][0]) dp[x][1] += dp[u][0]+1;//父节点放灯,并且子节点不放灯
		else dp[x][1] += dp[u][1];//两个都放灯
	}
}

void solve()
{
	int ans = 0;
	for(int i = 0;i < n;i++)//遍历节点
	{
		if(!v[i])//如果是没有遍历过的点,因为每次DFS都会把其子点遍历,这些点就没有必要了
		{
			dfs(i);
			ans += min(dp[i][0],dp[i][1]);//选择较小的
		}
	}
	printf("%d %d %d\n",ans/M,m-ans%M,ans%M);
}

int main()
{
	int T; scanf("%d",&T);
	while(T--)
	{
		init();
		solve();
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章