列表

详情


NC233444. 三千道路

描述

给出一张 n 个点 m 条边的有向图,求是否存在一张竞赛图的连通性与给定的有向图连通性相同。

竞赛图:若简单有向图 G 满足任意不同两点间都有恰好一条单向边,则称 G 为竞赛图。
连通性相同:我们称两张有向图 G_1G_2 连通性相同,当且仅当对于所有点 x,均满足它在 G_1G_2 中能到达的点集相同。

输入描述

本题有多组数据。
第一行为一个正整数 ,表示数据组数。
对于每组数据:
第一行依次输入两个正整数 ,表示给出有向图的点数和边数。
接下来 m 行,每行两个正整数 ,表示一条从点 x 连向点 y 的有向边。

输出描述

对于每组数据输出一行。

如果存在一张竞赛图和给定的有向图连通性相同,则输出 YES。

否则输出 NO。

示例1

输入:

3
4 4
1 3
1 2
2 3
3 4
4 4
1 2
1 3
3 4
2 4
5 6
1 2
2 3
3 4
4 5
5 2
1 4

输出:

YES
NO
YES

说明:

对于样例中的第一组数据,存在竞赛图与原图连通性相同。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 557ms, 内存消耗: 12920K, 提交时间: 2022-05-13 19:24:21

#include <bits/stdc++.h>
using namespace std;
inline void read(int &x)
{
    char c;int f=1;
    while(!isdigit(c=getchar()))if(c=='-')f=-1;
    x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
    x*=f;
}
inline void read(long long &x)
{
    char c;int f=1;
    while(!isdigit(c=getchar()))if(c=='-')f=-1;
    x=(c&15);while(isdigit(c=getchar()))x=(x<<1)+(x<<3)+(c&15);
    x*=f;
}
int t,n,m,i,j,dfn[100005],low[100005],col[100005],cnt,ti,stk[100005],tp,f[100005];
vector<int> v[100005];
bool flg;
void tarjan(int x)
{
	stk[++tp]=x;dfn[x]=low[x]=++ti;
	for(int u:v[x]){
		if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
		else if(!col[u]) low[x]=min(low[x],dfn[u]);
	}
	if(low[x]==dfn[x]){
		cnt++;int sz=1;
		while(stk[tp]!=x) col[stk[tp--]]=cnt,sz++;
		col[stk[tp--]]=cnt;
        if(sz==2) flg=0;
	}
}
void solve()
{
    flg=1;
	read(n);read(m);for(i=1;i<=n;i++)dfn[i]=low[i]=col[i]=0,v[i].clear(),f[i]=0;cnt=ti=0;
	while(m--){int x,y;read(x);read(y);v[x].push_back(y);}
	for(i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    if(!flg){puts("NO");return;}
	for(i=1;i<=n;i++)for(int u:v[i])if(col[u]==col[i]-1) f[col[i]]=1;
	for(i=2;i<=cnt;i++)if(!f[i]){
		puts("NO");return;
	}
	puts("YES");
}
int main()
{
	read(t);
	while(t--){
		solve();
	}
	return 0;
}

上一题