日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客假日团队赛8:H.Cell Phone Network(最小支配集)

發布時間:2024/9/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客假日团队赛8:H.Cell Phone Network(最小支配集) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/contest/1069/A
來源:??途W

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social interaction. This, however, requires him to set up cell phone towers on his N (1 ≤ N ≤ 10,000) pastures (conveniently numbered 1…N) so they can all communicate.
Exactly N-1 pairs of pastures are adjacent, and for any two pastures A and B (1 ≤ A ≤ N; 1 ≤ B ≤ N; A ≠ B) there is a sequence of adjacent pastures such that A is the first pasture in the sequence and B is the last. Farmer John can only place cell phone towers in the pastures, and each tower has enough range to provide service to the pasture it is on and all pastures adjacent to the pasture with the cell tower.
Help him determine the minimum number of towers he must install to provide cell phone service to each pasture.
輸入描述:

  • Line 1: A single integer: N
  • Lines 2…N: Each line specifies a pair of adjacent pastures with two space-separated integers: A and B
    輸出描述:
  • Line 1: A single integer indicating the minimum number of towers to install
    示例1
    輸入
    復制
5 1 3 5 2 4 3 3 5

輸出
復制

2

說明
The towers can be placed at pastures 2 and 3 or pastures 3 and 5.

一.題意:

給出直接相連的幾條邊,選擇最少的點,使所有點都被覆蓋(點能被覆蓋的條件是:與所選點 有邊直接相連)
這題實質上是求最小支配集

二.最小支配集的概念:

支配集的定義如下:給定無向圖G =(V , E),其中V是點集, E是邊集, 稱V的一個子集S稱為支配集當且僅當對于V-S中任何一個點v, 都有S中的某個點u, 使得(u, v) ∈E。
特別地,最小的支配集S(即任意一個比S小的集合都不可能是支配集)叫做最小支配集

三 .求解最小支配集的方法:

1.類似Tarjan且基于dfs的貪心
2.樹形dp

四.具體操作

解法一:
貪心:
1.選擇其中一個點作為root,定義father數組,并標記root的父親為自己。
2.定義一個dfsn數組,用于dfs時記錄每個點dfs序
3.dfs,dfs得到dfs序和每個點的father
4.定義一個s數組,作為支配集容器,
重新初始化vis,vis用于標記是否屬于支配集和是否與支配集中的點相連
記錄答案:按照dfs序的逆序依次選點
對于一個即不屬于支配集也不與支配集中的點相連的點來說
,如果他的父節點不屬于支配集,將其父節點加入到支配集,ans++,標記當前節點父節點屬于支配集s
標記當前結點、當前結點的父節點(屬于支配集)、當前結點的父節點的父節點(與支配集中的點相連)。

#include <bits/stdc++.h> using namespace std; const int MAXN = 1e4+5; vector<int>vec[MAXN]; int dfn[MAXN]; bool vis[MAXN]; int father[MAXN]; int s[MAXN]; int cnt; int n; void init() {for(int i = 0; i<= n; i++){vis[i] = false;} } void dfs(int s) {dfn[++cnt] = s ;int iSize = vec[s].size();for(int i = 0; i < iSize; i++){int to = vec[s][i];if(!vis[to]){father[to] = s;vis[to] = true;dfs(to);}}return; } int solve() {father[1] = 1;vis[1] = true;dfs(1);init();int ans = 0;for(int i = cnt; i > 0; i--){int x = dfn[i];if(!vis[x])//不屬于支配集也不與支配集中的點相連{if(!s[father[x]])//它的父節點不屬于支配集{ans++;s[father[x]] = true;//父節點入支配集}vis[x] = true;//標記自己vis[father[x]] = true;//標記自己的父親vis[father[father[x]]] = true;//標記自己父親的父親}}return ans; } int main() {cin>>n;int x,y;for(int i = 1; i < n; i++){cin>>x>>y;vec[x].push_back(y);vec[y].push_back(x);}cout<<solve()<<endl;return 0; }

解法二:
dp:(我表示并不會)
請參考下面來自百度百科的代碼:

#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int MAXN=10010; const int INF=int(1e7); struct node { int to; int next; } edge[MAXN*2]; int head[MAXN*2],num; int dp[MAXN][3]; /* 1):dp[i][0],表示點 i 屬于支配集合, 并且以點 i 為根的子樹都被覆蓋了的情況下支配集中所包含最少點的個數. 2):dp[i][1],表示點 i 不屬于支配集合,且以 i 為根的子樹都被覆蓋, 且 i 被其中不少于一個子節點覆蓋的情況下支配集所包含最少點的個數. 3):dp[i][2],表示點 i 不屬于支配集合, 且以 i 為根的子樹都被覆蓋,且 i 沒被子節點覆蓋的情況下支配集中所包含最少點的個數.即 i 將被父節點覆蓋. */ int n; void add(int x,int y) { edge[++num].next=head[x]; edge[num].to=y; head[x]=num; } void DP( int k,int fat ) { dp[ k ][ 0 ]=1; dp[ k ][ 2 ]=0; bool s=0; int x,sum=0,inc=INF; for(int i=head[ k ]; i ;i=edge[i].next ) { x=edge[i].to; if( x==fat ) continue ; DP( x,k ); dp[ k ][ 0 ]+=min(dp[ x ][ 0 ],min(dp[ x ][ 1 ],dp[ x ][ 2 ])); if( dp[ x ][ 0 ] <= dp[ x ][ 1 ] ) { sum+=dp[ x ][ 0 ]; s=1; } else { sum+=dp[ x ][ 1 ]; inc=min(inc,dp[ x ][ 0 ]-dp[ x ][ 1 ]); } if( dp[ x ][ 1 ]!=INF && dp[ k ][ 2 ]!=INF ) //x不是葉子節點,而且k有父親,即k不是根 dp[ k ][ 2 ]+=dp[ x ][ 1 ]; else dp[ k ][ 2 ]=INF; } if( inc==INF && !s )//k沒有子節點 dp[ k ][ 1 ]=INF; else { dp[ k ][ 1 ]=sum; if( !s )//如果不為零,則k的子節點中有一個已經染色 dp[ k ][ 1 ]+=inc; } return ; } int main() { int u,v; scanf("%d",&n); for(int i=1; i<=n-1; i++) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } DP( 1,0 ); int ans=min(dp[1][0],dp[1][1]); printf("%d\n",ans); return 0;

總結

以上是生活随笔為你收集整理的牛客假日团队赛8:H.Cell Phone Network(最小支配集)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。