HDU 2767 Proving Equivalences (强联通分量模板)

题目描述:给你n个式子,有m种已知关系,问至少还需添加几种关系,使得这n个式子两两互证。

思路:DAG上的两个点能两两互达,说明是这个图的scc只有一个,那么我们可以重新构造这个图,先找出这个图的所有的scc,然后把每一个scc看作一个点,那么得到一个新的DAG图,那么问题就转化为,DAG上连数目最少的边,使得整个图所有的点能两两互达。显然这个答案是max(in0,out0)。in0代表图中入度为0的点,out0代表出度为0的点。为什么呢,对于一个图来说,它所有的点既有出边,又有入边,那么这个图必然所有点都互达,那么连接一条边,从图中in0到out0,就可以使得图中in0--,out0--,最少添加max(in0,out0)就使得in0 = 0,out0 = 0。注意,如果此图是一个scc,那么答案为0.

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn = 2e4+10;
vector<int>G[maxn];

int pre[maxn],low[maxn],scc[maxn];
int dfs_clock,scc_cnt;
stack<int>s;
void dfs(int u)
{
	pre[u] = low[u] = ++dfs_clock;
	s.push(u);
	for(int i=0;i<G[u].size();i++)
	{
		int v = G[u][i];
		if(!pre[v])
		{
			dfs(v);
			low[u] = min(low[u],low[v]);
		}
		else if(!scc[v])low[u] = min(low[u],pre[v]);
	}
	if(low[u] == pre[u])
	{
		++scc_cnt;
		while(1)
		{
			int x = s.top();
			s.pop();
			scc[x] = scc_cnt;
			if(x == u)break;
		}
	}
}
void find_scc(int n)
{
	dfs_clock = scc_cnt = 0;
	memset(pre,0,sizeof(pre));
	memset(scc,0,sizeof(scc));
	for(int i=1;i<=n;i++)
	if(!pre[i])dfs(i);
}
int in[maxn],out[maxn];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,m;
		scanf("%d%d",&n,&m);
		
		for(int i=1;i<=n;i++)G[i].clear();
		for(int i=1;i<=m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			G[u].pb(v);
		}
		find_scc(n);
		for(int i=1;i<=scc_cnt;i++)in[i] = out[i] = 1;
		for(int u=1;u<=n;u++)
		for(int i=0;i<G[u].size();i++)
		{
			int v = G[u][i];
			if(scc[u]!=scc[v])in[scc[v]] = out[scc[u]] = 0;
		}
		int a=0,b=0;
		for(int i=1;i<=scc_cnt;i++)
		{
			if(in[i])++a;
			if(out[i])++b;
		}
		int ans = max(a,b);
		if(scc_cnt == 1)ans = 0;
		printf("%d\n",ans);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值