# 題目
AP325 Q-8-9. 服務中心選位置
# 解題思路
這題是最小支配集問題,我下面的是假解我當時還沒學到這個問題,手搓了個奇怪的解,不過也 AC 了看來我有寫假解的天賦,
#include<bits/stdc++.h> | |
using namespace std; | |
#define N 100005 | |
int total=0,chose[N]={0}; | |
vector<int> path[N]; | |
void dfs(int r,int p){//p = parent | |
for(auto e:path[r]){ | |
if(e==p) continue; | |
dfs(e,r); | |
if(chose[r]==1) | |
chose[e]=1; | |
else if(chose[e]==0){ | |
if(p!=-1 && chose[p]==0) chose[p]=2; | |
chose[r]=1; | |
chose[e]=1; | |
total++; | |
} | |
} | |
} | |
int main(){ | |
int n,num[N]={1},point=1; | |
cin>>n; | |
for(int i=1,u,v;i<n;i++){ | |
cin>>u>>v; | |
num[u]++; | |
num[v]++; | |
path[u].push_back(v); | |
path[v].push_back(u); | |
if(num[u]>num[point]) point=u; | |
if(num[v]>num[point]) point=v; | |
} | |
dfs(point,-1); | |
if(chose[point]==0){ | |
total++; | |
} | |
cout<<total; | |
return 0; | |
} |
# AC 程式碼
#include<bits/stdc++.h> | |
using namespace std; | |
#define Rabbir_Reaper ios::sync_with_stdio(0);cin.tie(0); | |
#define int long long | |
const int N = 100005; | |
vector<int> adj[N]; | |
int dp[N][3]; | |
// 0 : 不選此點,未被支配 | |
// 1 : 不選此點,已被子節點支配 | |
// 2 : 選取此點,已被自己支配 | |
void dfs(int x,int p){ | |
dp[x][0] = 0; | |
dp[x][1] = 1e5; | |
dp[x][2] = 1; | |
int sum=0; | |
for(auto &u:adj[x]){ | |
if(u == p) continue; | |
dfs(u,x); | |
dp[x][0] += dp[u][1]; | |
sum += min(dp[u][1],dp[u][2]); | |
dp[x][2] += min({dp[u][0],dp[u][1],dp[u][2]}); | |
} | |
for(auto &u : adj[x]){ | |
if(u == p) continue; | |
dp[x][1] = min(dp[x][1], sum - min(dp[u][1], dp[u][2]) + dp[u][2]); | |
} | |
} | |
signed main(){ | |
int n; | |
cin>>n; | |
n--; | |
for(int i=0,u,v;i<n;i++){ | |
cin>>u>>v; | |
adj[u].push_back(v); | |
adj[v].push_back(u); | |
} | |
dfs(1,-1); | |
cout<<min(dp[1][1],dp[1][2]); | |
} |