CF732F Tourist Reform(dfs树、边双连通图、tarjan)

因为知道了算法tag,所以想到了正解:

先给出两个性质:

  1. 边双给边定向一定可以转为强连通图,此为最优解
  2. 树给边定向后R的最小值必为0

性质2证明如下:

设树有n个节点,
若R_min!=0,
则每点出度至少为1,各点出度之和至少为n,
则至少有n条边,但树只有n-1条边,矛盾

那么这道题只要在原图上把边双缩成点即可

问题是如何构造?

要解决树的构造很简单,因为树上必有一点无法到达其它节点,而我们又要令R_min最大,那么就令这个无法到达其它节点的点为 包含点的个数最多的边双 代表的点 ,把这个点当做 根节点 dfs这棵树,把树上的边(原图上的桥)定向为 son—>fa,可以保证R_min=根节点代表的边双包含点的个数

然后就是我想不到的了,边双内部要如何构造呢?

虽然我自己想了一种构造方法,但是T得十分惨烈……

然后,第二天我去学习了dfs树,发现这个问题变得很简单

这是我最后用的构造方案:

void dfs(int u){
   
	vis[u]=1;
	for(int i=head[u];i!=-1;i=edge_nxt[i]){
   
		int v=edge_v[i];
		if(edge_br[i]){
   
			add_e(edge_u[i],edge_v[i],edge_id[i]);
			continue;
		}
		if(!aa[edge_id[i]]) aa[edge_id[i]]=u,bb[edge_id[i]]=v;//加判断是为了防止将定好向的(fa[u],u)边再反向 
		if(!vis[v]) dfs(v);
	}
}

为什么可行?

用dfs树理解,这个构造方案就是将所有树边定向向下并将所有回边定向向上,由dfs树的性质知这一定可行

最后放上完整代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
const int N=4e5+5;
int edge_u[N<<1],edge_v[N<<1],edge_id[N<<1],edge_nxt[N<<1],edge_br[N<<1];
int n,m,head[N],cnt,a[N],b[N]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值