1. 树的最长路径
注意
错误的dfs,应当用temp去更新d1和d2,而不是dist。
int dfs(int now, int father){
int dist = 0;
int d1 = 0, d2 = 0;
for(int i=head[now]; ~i; i = edge[i].next){
int to = edge[i].to;
if(to == father) continue;
int temp = dfs(to, now) + edge[i].wei;
if(dist > d1) d2 = d1, d1 = dist;
else if(dist > d2) d2 = dist;
dist = max(dist, temp);
}
ans = max(ans, d1 + d2);
return dist;
}
AC代码:
/*
* Author: Chen_zhuozhuo
* Created Time: 2020/3/21 20:50:12
* File Name: a.cpp
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxint = -1u>>1;
const int inf = 0x3f3f3f3f;
const int maxn = 1e4+10;
int n,from,to,wei;
int cnt = 1;
int vis[maxn];
int ans = 0;
int head[maxn];
struct Edge{
int next, to, wei;
}edge[maxn<<1];
void addedge(int from, int to, int wei){
edge[cnt].to = to;
edge[cnt].wei = wei;
edge[cnt].next = head[from];
head[from] = cnt ++;
}
int dfs(int now, int father){
int dist = 0, d1 = 0, d2 = 0;
for(int i = head[now]; ~i; i = edge[i].next){
int to = edge[i].to;
if(to == father) continue;
int d = dfs(to, now) + edge[i].wei;
if(d > d1) d2 = d1, d1 = d;
else if(d > d2) d2 = d;
dist = max(dist, d);
}
ans = max(ans, d1 + d2);
return dist;
}
void init(){
for(int i=0;i<=n;i++){
head[i] = -1;
}
}
int main() {
cin>>n;
init();
for(int i=1;i<n;i++){
cin>>from>>to>>wei;
addedge(from, to, wei);
addedge(to, from, wei);
}
dfs(1, -1);
cout<<ans<<endl;
return 0;
}
2. Interesting Vertices
题意
一棵树,k个点被染色,定义interesting点:每一个以直接孩子为根的子树都至少有一个节点被染色。求多少个染色点,并从小到大输出节点编号。
思路
队友用正反两次搜索过了(反向搜索用map存点)。我用树形dp。
从染色点开始搜索,对每一个节点定义两个属性interesting和其dfs的返回值。
dfs返回值(true表示,以node[i]做根的子树存在染色点)
判定条件
dfs返回值true的条件:染色点 或 其子树dfs返回值为true
interesting的条件: 子树返回值累加和 = 度数减1
解释: interesting的条件:是因为我们从染色点开始搜索,也就是某点的上方一定有一个染色点,所以等于度数减1就可以了。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int maxn = 2e5 + 10;
const double esp = 1e-6;
const int inf = 0x3f3f3f3f;
int n, k, cnt = 1, from, to;
int head[maxn];
int degree[maxn];
int col[maxn];
int itst[maxn];
struct EDGE{
int next, to;
}edge[maxn << 1];
void init(){
for(int i=0;i<=n;i++){
head[i] = -1;
}
}
void addedge(int from, int to){
edge[cnt].to = to;
edge[cnt].next = head[from];
head[from] = cnt ++;
}
// tree-format dynamic programming
bool dfs(int now, int father){
int cnt = 0;
for(int i=head[now]; ~i; i=edge[i].next){
int to = edge[i].to;
if(to == father) continue;
if(dfs(to, now)) cnt ++;
}
if(col[now])
return true;
if(cnt == degree[now] - 1)
itst[now] = 1;
if(cnt)
return true;
return false;
}
int main(){
scanf("%d%d", &n, &k);
init();
for(int i=1;i<=k;i++){
scanf("%d", &from);
col[from] = 1;
}
for(int i=1;i<n;i++){
scanf("%d%d", &from, &to);
addedge(from, to), addedge(to, from);
degree[from] ++, degree[to] ++;
}
for(int i=1;i<=n;i++){
if(col[i]){
dfs(i, -1);
break;
}
}
int ans = 0;
for(int i=1;i<=n;i++){
if(itst[i])
ans ++;
}
printf("%d\n", ans);
for(int i=1;i<=n;i++){
if(itst[i])
printf("%d ", i);
}
puts("");
return 0;
}
/*
inputCopy
4 1
3
1 2
2 3
2 4
outputCopy
2
1 4
inputCopy
8 3
6 5 7
1 5
5 4
5 3
1 6
2 7
1 2
1 8
outputCopy
4
2 3 4 8
*/