洛谷P11380 [GESP202412 八级] 排队 题解

数据太可恶了,竟然有重边!!!

题目传送门。

显然一道简单图论题。

\(a_i\)\(b_i\) 的关系想象成一条有向边,于是可以得出:如果 \(x\) 的出度大于 \(1\) 或者 \(x\) 的入度大于 \(1\) 或者图中存在环,那么无解。然后有解的话怎么计数?也很简单,因为一个联通块内肯定是无法变动的了,所以只能连通块之间互换顺序,所以说答案为联通块数量的阶乘。

十年 OI 一场空,不开 long long 见祖宗。

三年 OI 一场空,出现重边见祖宗。

本来我是可以在读入的时候发现无解直接输出 \(0\) 然后退出的,但是某些 OJ 这么做会出现问题(个人亲身经历),所以我就用了一个 \(flag\) 变量记录是否无解。

使用 \(flag\) 代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
const int mod = 1e9+7;
vector<int>a[N];
int chu[N];
int ru[N];
int f[N];
int tong;
int find(int x)
{
	return x == f[x]?x:f[x] = find(f[x]);
}
signed main()
{
	int flag = 1;
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i = 1;i<=n;i++)
	{
		f[i] = i;
	}
	for(int i = 1;i<=m;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		int xx = find(x),yy = find(y);
		if(find(a[x].begin(),a[x].end(),y)!=a[x].end())
		{
			continue;
		}
		if(xx == yy)
		{
			flag = 0;
		}
		f[xx] = yy;
		a[x].push_back(y);
		chu[x]++;
		ru[y]++;
		if(chu[x]>1||ru[y]>1)
		{
			flag = 0;
		}
	}
	if(!flag)
	{
		printf("0");
		return 0;
	}
	for(int i = 1;i<=n;i++)
	{
		if(f[i] == i)
		{
			tong++;
		}
	}
	long long sum = 1;
	for(int i = 1;i<=tong;i++)
	{
		sum = sum*i%mod;
	}
	printf("%lld",sum);
	return 0;
}

不使用 \(flag\) 代码(这份代码在洛谷可以通过,但是我不确定其它版本的评测机是否能行,为了保守,大家最好不要使用此代码):

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
const int mod = 1e9+7;
vector<int>a[N];
int chu[N];
int ru[N];
int f[N];
int tong;
int find(int x)
{
	return x == f[x]?x:f[x] = find(f[x]);
}
signed main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i = 1;i<=n;i++)
	{
		f[i] = i;
	}
	for(int i = 1;i<=m;i++)
	{
		int x,y;
		scanf("%d %d",&x,&y);
		int xx = find(x),yy = find(y);
		if(find(a[x].begin(),a[x].end(),y)!=a[x].end())
		{
			continue;
		}
		if(xx == yy)
		{
			printf("0");
			return 0;
		}
		f[xx] = yy;
		a[x].push_back(y);
		chu[x]++;
		ru[y]++;
		if(chu[x]>1||ru[y]>1)
		{
			printf("0");
			return 0;
		}
	}
	for(int i = 1;i<=n;i++)
	{
		if(f[i] == i)
		{
			tong++;
		}
	}
	long long sum = 1;
	for(int i = 1;i<=tong;i++)
	{
		sum = sum*i%mod;
	}
	printf("%lld",sum);
	return 0;
}
posted @ 2025-02-20 15:11  林晋堃  阅读(280)  评论(0)    收藏  举报