【最小支配集】开会

本文探讨了一种在图论中寻找最小支配集的算法实现,通过建立学生间绯闻关系的图模型,解决如何用最少的人数震慑整个群体的问题。算法采用深度优先搜索(DFS)和广度优先搜索(BFS)结合的方式,最终输出所需邀请的最少人数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

开会,是对所有人时间的浪费,是对集体的谋杀。
山区学校的一些学生之间的关系似乎好得有点过头,以至于传出了一些(在风纪委员们看来)不好的绯闻。具体地,有n个学生,n-1条绯闻,每条绯闻的主角都是俩学生。记者们的恶趣味保证任意两个学生,可以通过若干条绯闻直接或间接地联系在一起。
于是学校打算邀请一些学生参加座谈会。
校长相信,假如邀请了某位学生x来开会,那么就能够震慑到x本人,以及和x在同一条绯闻里的学生们。
矿泉水是宝贵的,校长想知道最少需要请多少人来开会,才有可能震慑到所有同学。
 


输入

第一行是 n 表示学生数。 
之后n-1行,每行俩整数x,y,表示学生x和y之间有绯闻。( x≠y,但不一定x<y )


输出

一行,一个整数表示最少要邀请多少人。 


样例输入

5
1 3
5 2
4 3
3 5

样例输出

2


提示

可以选择邀请学生2&3,或者是邀请学生3&5 

对于前10%的数据,n<=15
对于前30%的数据,n<=2000
对于接下来30%的数据,n<=10^5,且有俩学生需要通过n-1条绯闻才能扯上关系。
对于前100%的数据,n<=10^5,1<=x,y<=n

【题解】:

最小支配集:模板题

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1000;
typedef struct Edge{
    int v,next;
    Edge(int v=0,int next=0):v(v),next(next){}
}Edge;
Edge e[N*2];
int head[N],cnt,n;
int vis[N];
void add_edge(int u,int v){
    e[cnt]=Edge(v,head[u]);
    head[u]=cnt++;
}
int pre[N];
void dfs(int u,int father){
    pre[u]=father;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==father) continue;
        dfs(v,u);
    }
}
stack < int > St;
queue < int > q;
void bfs(){
    q.push(1);
    St.push(1);
    while(!q.empty()){
        int cur = q.front();
        q.pop();
        for(int i=head[cur];~i;i=e[i].next){
            int v=e[i].v;
            if(v==pre[cur])continue;
            q.push(v);
            St.push(v);
        }
    }
}
void solve(){
    int ans=0;
    while(!St.empty()){
        int cur=St.top();
        St.pop();
        if(vis[cur]==0){
            vis[pre[cur]]=1;
            for(int i=head[pre[cur]];~i;i=e[i].next){
                int v=e[i].v;
                vis[v]=1;
            }
            ans++;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add_edge(u,v);
        add_edge(v,u);
    }
    dfs(1,0);
    bfs();
    solve();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值