题目大意:给你一棵边权为1的树,让你加入一些边,使得根节点(1号节点)到其他节点的最短距离不大于2
并没有想到贪心......
正解的贪心思路是这样的
用一个堆维护当前距离最远的点,然后把根节点和它的父节点连起来
这样,父节点周围一圈的节点到根的距离都不大于2,把这些节点都从堆里删除
实际操作的时候,并不需要删除它们,只需要把它们标记一下,等它们弹出堆的时候,continue即可
不断按照这个思路贪心,直到所有节点到根的距离都不大于2即可
1 #include <set> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #define N 200010 7 #define ll long long 8 using namespace std; 9 //re 10 int gint() 11 { 12 int ret=0,fh=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 14 while(c>='0'&c<='9'){ret=ret*10+c-'0';c=getchar();} 15 return ret*fh; 16 } 17 int n,m,K,ma,cte,num; 18 int head[N],vis[N],use[N],dis[N],fa[N]; 19 struct Edge{int to,nxt,val;}edge[N*2]; 20 void ae(int u,int v){ 21 cte++;edge[cte].to=v; 22 edge[cte].nxt=head[u],head[u]=cte;} 23 struct node{ 24 int id,d; 25 friend bool operator<(const node &s1,const node &s2) 26 {return s1.d<s2.d;} 27 node(int id,int d):id(id),d(d){} node(){} 28 }; 29 void bfs() 30 { 31 queue<int>q;q.push(1); 32 while(!q.empty()) 33 { 34 int u=q.front();q.pop(); 35 for(int j=head[u];j;j=edge[j].nxt){ 36 int v=edge[j].to; 37 if(v==fa[u]) continue; 38 fa[v]=u,dis[v]=dis[u]+1; 39 q.push(v); 40 } 41 } 42 } 43 int solve() 44 { 45 priority_queue<node>q; 46 for(int i=1;i<=n;i++) 47 if(dis[i]>2) q.push(node(i,dis[i])); 48 int ans=0; 49 while(!q.empty()) 50 { 51 node k=q.top();q.pop(); 52 int x=k.id,y=fa[x]; 53 if(vis[x]) continue; vis[x]=1; 54 dis[y]=1,vis[y]=1,ans++; 55 for(int j=head[y];j;j=edge[j].nxt){ 56 int v=edge[j].to; 57 dis[v]=min(dis[v],2),vis[v]=1; 58 q.push(node(v,dis[v])); 59 } 60 }return ans; 61 } 62 63 int main() 64 { 65 scanf("%d",&n); 66 int x,y,z,fx; 67 for(int i=1;i<n;i++) 68 x=gint(),y=gint(),ae(x,y),ae(y,x); 69 bfs(); 70 printf("%d ",solve()); 71 return 0; 72 }