BZOJ3037: 创世纪

该博客讨论了一道题目的解决方案,题目涉及有向图的处理,其中每个点的出度为1。问题要求将节点分为两组,一组支配另一组,目标是最大化被支配组的大小。博主提出了两种方法,一是转化为求最小支配集问题,通过反向图和贪心策略解决;二是直接在原图上进行贪心操作,通过拓扑排序处理环形结构。注意点在于正确理解问题要求是求最大被支配集而非最小支配集。
摘要由CSDN通过智能技术生成

题目大意:给定一个有向图,每个点出度为1,让你将这些点分为两个集合x和y,使得对于每一个y集合内的点都存在一个x集合内的点指向它,并且使得y集合尽可能大。
原图给的是一些内向基环树,显然要求的是一个最小支配集@poj3659。内向的基环树我们不好处理,考虑将这颗树反向,变成了外向基环树,这样我们可以随便找到环上的一个点以及指向它的点(首先每个联通快一定有环,但其实没有环的话就是正常的树了),不妨设为y->x,枚举x选择还是不选择,如果x选了,那么y就有人支配了,以x为根做正常的最小支配集即可。
做最小值配集的时候有一个小技巧tmp,有兴趣可以阅读下…
(还有一种直接贪心乱搞的做法在下面…)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
//by:MirrorGray
using namespace std;
const int N=1111111;
int tot=-1,head[N],ver[N],nxt[N];
int root,f[N],g[N],fa[N],vis[N],ban[N];

void add(int x,int y){
    nxt[++tot]=head[x];
    head[x]=tot;
    ver[tot]=y;
}

int find(int x){
    vis[x]=true;
    return vis[fa[x]]?x:find(fa[x]);
}

void dfs(int x){
    vis[x]=true;f[x]=1;g[x]=0;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值