标签:blog os io ar for div cti sp log
dfs+记忆化搜索,白书上给了一种很神的存答案的方式,要同时保存两个值,可以将一个值乘以一个大整数加上另外一个。
具体状态转移见注释
#include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include <bitset> #include <list> #include <cstdlib> #include <climits> #include <cmath> #include <ctime> #include <algorithm> #include <stack> #include <sstream> #include <numeric> #include <fstream> #include <functional> using namespace std; #define MP make_pair #define PB push_back typedef long long LL; typedef unsigned long long ULL; typedef vector<int> VI; typedef pair<int,int> pii; const int INF = INT_MAX / 3; const double eps = 1e-8; const LL LINF = 1e17; const double DINF = 1e60; const int maxn = 1005; VI e[maxn]; int n, m, vis[maxn][2], note[maxn][2]; int dfs(int i, int j, int f) { if(vis[i][j]) return note[i][j]; vis[i][j] = 1; int &ret = note[i][j] = INF; //如果当前节点不放灯(父亲节点必须放灯) //总数为每一个节点的和 × 2000 + 1 //需要对根节点进行特判 int sum = f == -1 ? 0 : 1, mm = e[i].size(); if(j) { for(int nx = 0;nx < mm;nx++) if(e[i][nx] != f) { sum += dfs(e[i][nx], 0, i); } ret = sum; } //当前节点放灯 //总数为每一个节点的和*2000,然后如果父亲节点没有灯,再+1 sum = j == 0 ? 1 : 0; for(int nx = 0;nx < mm;nx++) if(e[i][nx] != f) { sum += dfs(e[i][nx], 1, i); } sum += 2000; ret = min(sum,ret); return ret; } int main() { int T; scanf("%d",&T); while(T--) { memset(vis,0,sizeof(vis)); memset(note,0,sizeof(note)); scanf("%d%d",&n,&m); for(int i = 0;i < n;i++) e[i].clear(); for(int i = 0;i < m;i++) { int a,b; scanf("%d%d",&a,&b); e[a].PB(b); e[b].PB(a); } //当前节点,父节点有没有点亮,父节点编号 //dfs(i,j,k) //枚举森林中的每一棵树 int ans = 0; for(int i = 0;i < n;i++) if(!vis[i][0]) { ans += dfs(i,1,-1); } printf("%d %d %d\n",ans / 2000,m - ans % 2000,ans % 2000); } return 0; }
UVA 10859 Placing Lampposts 树形DP
标签:blog os io ar for div cti sp log
原文地址:http://www.cnblogs.com/rolight/p/3959200.html