Codeforces 711D Directed Roads dfs(找环)

点击打开链接

题意:给定n个点n条边(n<=2e5)的有向图,每个顶点都只有一条出边,给定op:将若干条边翻转,问有多少种op使得,操作后的图不存在环 

关键:因为每个点的出边只有一个,若有u->v路径无环,则u->v为简单的路径只有n-1条边,则该路径边可以随意反转 (v的出边可能和其他边形成环)
在环上的边至少反转一条即可变为无环(环变为若干条链),但不能全部翻转.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=2e5+20;
int to[N];//每个点出度为1 
int T,n,id[N],tim[N];
vector<int> num;//每个环上的顶点数
ll d[N];//2^i mod 1e9
void dfs(int x,int t)
{
	id[x]=t;//dfs顺序 
	tim[x]=T;//第T个连通分量 

	int v=to[x];
	if(id[v]!=-1&&tim[v]==T)//找到环 
	{
		num.push_back(id[x]-id[v]+1);//环上的点 
	}
	else if(id[v]==-1)
	{
		dfs(v,t+1);
	}
} 
int main()
{
	d[0]=1;
	for(int i=1;i<N;i++)
	d[i]=(d[i-1]*2ll)%mod;
	
	while(cin>>n)
	{
		memset(id,-1,sizeof(id));
		T=0;
		
		for(int i=1;i<=n;i++)
		{
			int x;
			scanf("%d",&x);
			to[i]=x;	
		}
		for(int i=1;i<=n;i++)//遍历每个连通分量 
		{ 
			if(id[i]==-1)// 
			{
				++T;
				dfs(i,1);
			}
		}
		ll ans=1,cnt=0;//
		for(int i=0;i<num.size();i++)
		{
			//环上边不能全翻转和都不翻转 
			ans=ans*(d[num[i]]-2+mod)%mod;
			cnt+=num[i];
		}
		cnt=n-cnt;
		ans=(ans*d[cnt])%mod;//不在环上的边 
		cout<<ans<<endl;	
		num.clear();
		
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值