Cell Phone Network
Cell Phone Network
題意:
每個(gè)牧場(chǎng)的電塔可以覆蓋與該牧場(chǎng)相鄰的電塔,為了讓所有牛都可以打電話,求建的電塔的最小數(shù)量
題解:
樹(shù)的最小支配集
dp[x][0]:選點(diǎn)i,并且以點(diǎn)i為根的子樹(shù)都被覆蓋
dp[x][1]:不選i,i被其兒子覆蓋
dp[x][2]:不選點(diǎn)i,i被其父親覆蓋(此時(shí)兒子可選可不選)
轉(zhuǎn)移方程:
dp[i][0]=1+∑min(dp[u][0],dp[u][1],dp[u][2])(u是i的兒子)
被兒子被自己被父親覆蓋
dp[i][2]=∑(dp[u][1],dp[u][0])
i被父親覆蓋,u是i的兒子,u 可選可不選,但是u肯定不會(huì)被i所覆蓋
對(duì)于dp[i][1]情況,i的兒子們中必須有一個(gè)取dp[u][0]
if(i沒(méi)有子節(jié)點(diǎn))dp[i][1]=INF
else dp[i][1]=∑min(dp[u][0],dp[u][1])+inc
對(duì)于inc
if(∑min(dp[u][0],dp[u][1])中包含某個(gè)dp[u][0])inc=0
else inc=min(dp[u][0]-dp[u][1])
選與不選
若dp[u][0]>dp[u][1],即所有子節(jié)點(diǎn)都不染色,所以我們必須強(qiáng)迫一個(gè)子節(jié)點(diǎn)染色且保證最優(yōu)解dp[root][1]+=min;
代碼:
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b) typedef long long ll; using namespace std;inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } const int maxn=1e4+9; const int INF=1e9+9; vector<int>vec[maxn]; /* dp[u][0]表示節(jié)點(diǎn)u建站點(diǎn)最少數(shù)目 dp[u][1]表示節(jié)點(diǎn)u的子節(jié)點(diǎn)有建,u不建 dp[u][2]表示節(jié)點(diǎn)u能夠被父親節(jié)點(diǎn)覆蓋,u不建 */ int vis[maxn]; int dp[maxn][5]; void dfs(int u) {dp[u][0]=1;dp[u][1]=dp[u][2]=0;vis[u]=1;int Min=INF;bool f=1;for(int i=0;i<vec[u].size();i++){int v=vec[u][i];if(vis[v])continue;dfs(v);dp[u][0]+=min(dp[v][0],min(dp[v][1],dp[v][2]));dp[u][2]+=min(dp[v][0],dp[v][1]);if(dp[v][0]<=dp[v][1]){f=0;dp[u][1]+=dp[v][0];}else {dp[u][1]+=dp[v][1];Min=min(dp[v][0]-dp[v][1],Min);}}if(f)dp[u][1]+=Min;} int main() {int n;cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v;vec[u].push_back(v);vec[v].push_back(u);}dfs(1);printf("%d\n",min(dp[1][0],dp[1][1]));return 0; }總結(jié)
以上是生活随笔為你收集整理的Cell Phone Network的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 医院能配眼镜贵吗
- 下一篇: Axial symmetry FZU -