Codeforces Round #565 (Div. 3) E (最小支配集)

http://codeforces.com/contest/1176/problem/E
题意: n 个 点 m 条 边 组 成 的 无 自 环 图 , 要 求 选 出 不 超 过 ⌊ n / 2 ⌋ 个 点 , 使 得 图 中 剩 余 的 其 他 点 都 与 选 出 的 点 有 边 相 连 , 输 出 这 些 点 n个点m条边组成的无自环图,要求选出不超过⌊n/2⌋个点,使得图中剩余的其他点都与选出的点有边相连,输出这些点 nmn/2,使

题解: 读 懂 题 目 就 知 道 这 是 个 最 小 支 配 集 的 裸 题 , 直 接 上 模 板 读懂题目就知道这是个最小支配集的裸题,直接上模板
这题卡memset 赛后叉了一大片。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5+5;
int pre[maxn];
bool visit[maxn];
int newpos[maxn*3];
int now;
int n, m;
int tot;
int head[maxn];
struct Node {int to; int next;};
Node edge[maxn*3];
void add(int u,int v){
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void DFS(int x) {
    newpos[now ++] = x;
    for(int k = head[x]; k != -1; k = edge[k].next) {
        if(!visit[ edge[k].to ]) {
            visit[ edge[k].to ] = true;
            pre[edge[k].to] = x;
            DFS(edge[k].to);
        }
    }
}
bool s[maxn],st[maxn];
int MDS() {
    int ans = 0;
    for(int i = n - 1; i >= 0; i--) {
        int t = newpos[i];
        if(!s[t]) { 
            if(! st[ pre[t] ]) {
                st[ pre[t] ] = true;
                ans ++; 
            }
            s[t] = true;
            s[ pre[t] ] = true;
            s[ pre[ pre[t] ] ] = true;
        }
    }
    int cnt = 0;
    printf("%d\n",ans);
    for(int i = 1; i <= n; i++){
        if(st[i]){
            cnt++;
            if(cnt > n/2) break;
            printf("%d ",i);
        }
    }
    puts("");
}

int main() {
    int T;
    cin>>T;
    while(T--){
        tot = 0;
        cin>>n>>m;
        int u,v;
        for(int i = 0; i <= n; i++)
			head[i] = -1; 
		for(int i = 0; i <= n; i++)
			visit[i] = false; 
        for(int i = 0; i <= n; i++)
            s[i] = false; 
        for(int i = 0; i <= n; i++)
            st[i] = false; 
        while(m--){
            cin>>u>>v;
            add(u,v);
            add(v,u);
        }
        
        now = 0;
        visit[1] = true;
        pre[1] = 1;
        DFS(1);
        MDS();
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值