牛客挑战赛 60 D三千道路

link

思路

缩点之后 如果有大小为2的联通块肯定不符合题意
之后再进行 拓扑排序 如果拓扑序唯一 则符合 否则不符合

#include <bits/stdc++.h>
using namespace  std;
#define  int long long
//typedef long long ll;
typedef pair<int,int> pii;
#define x first
#define y second
#define pb  push_back
#define inf 1e18
#define IOS   std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define  fer(i,a,b)  for(int i=a;i<=b;i++)
#define  der(i,a,b)  for(int i=a;i>=b;i--)
const int maxn=1e5+10;
const int mod=1e9+7;
int qmi(int a,int b) {
	int res=1;
	while(b) {
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
const int N=2e5+10;
int dr[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
int n,k;
int  m;
int low[N];
int dfn[N],ins[N],idx,cnt;
vector<int>g[N];
vector<int>e[N];
int bel[N];
int sz[N];
stack<int>s;
void dfs(int u) {
	dfn[u] = low[u] = ++idx;
	ins[u] = true;
	stk.push(u);
	for (auto v : e[u]) {
		if (!dfn[v]) dfs(v);
		if (ins[v]) low[u] = min(low[u], low[v]);
	}
	if (dfn[u] == low[u]) {
		++cnt;
		while (true) {
			int v = s.top();
			ins[v] = false;
			bel[v] = cnt;
			sz[cnt]++;
			s.pop();
			if (v == u) break;
		}
	}
}
int d[N];
bool   to(){
	queue<int>q;
	fer(i,1,cnt){
		if(!d[i])q.push(i);
	}
	int f=1;
	while(!q.empty()){
		int u=q.front();
		if(q.size()>1)f=0;
        q.pop();

		for(auto v:e[u]){
			if(!--d[v])q.push(v);
		}
	}
	return f;
}
void solve() {
	cin>>n>>m;
	fer(i,1,m) {
		int a,b;
		cin>>a>>b;
		g[a].push_back(b);
		//g[b].push_back(a);
	}
	fer(i,1,n)if(!dfn[i])dfs(i);
	fer(i,1,n) {
		for(auto v:g[i]) {
			if(bel[i]!=bel[v])e[bel[i]].push_back(bel[v]),d[bel[v]]++;
		}
	}
  //  cout<<cnt;
	fer(i,1,cnt) {
        cout<<sz[i];
		if(sz[cnt]==2) {
			cout<<"NO"<<endl;
			return ;
		}
	}
	if(to())cout<<"YES"<<endl;
	else  cout<<"NO"<<endl;
    while(!s.empty())s.pop();
    for(int i=1;i<=n;i++){
    	bel[i]=dfn[i]=low[i]=cnt=sz[i]=ins[i]=d[i]=idx=0;
    	g[i].clear();
    	e[i].clear();
	}
	}

signed main() {
	IOS;
	int _;
	cin>>_;
	while(_--) solve();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值