3444: 最后的晚餐(乱搞)

本文探讨了一种解决特定社交场景下座位安排问题的算法。该问题涉及将学生按其偏好进行排列,使得每个人尽可能与心仪的对象相邻。通过构建图论模型并运用搜索算法,文章提出了一种高效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

【问题背景】
高三的学长们就要离开学校,各奔东西了。某班n人在举行最后的离别晚餐时,饭店老板觉得十分纠结。因为有m名学生偷偷找他,要求和自己暗恋的同学坐在一起。
【问题描述】
饭店给这些同学提供了一个很长的桌子,除了两头的同学,每一个同学都与两个同学相邻(即坐成一排)。给出所有信息,满足所有人的要求,求安排的方案总数(这个数字可能很大,请输出方案总数取余989381的值,也可能为0)。

题解:
可以发现对于每个联通块只有两种排列方式,

对于每个联通快之间,可以用全排列。

然后就乱搞一下。。。

感觉基佬紫好像还挺好看的(滑稽)

今天是开始停课的-1天,希望noip rp++

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define mod 989381
using namespace std;
const int N=500100;
int n,m;
struct node{
	int x,y,next;
}sa[N*2];int len=1,first[N];
int ss[N];
void ins(int x,int y)
{
	len++;
	sa[len].x=x;
	sa[len].y=y;
	sa[len].next=first[x];
	first[x]=len;
}
int cnt=0;
bool tf[N],flag,ou;
map<int,int>f[N]; 
void dfs(int x,int fa)
{
	tf[x]=1;
	if(flag==1) return;
	for(int i=first[x];i!=-1;i=sa[i].next)
	{
		int y=sa[i].y;
		if(y!=fa)
		{
			if(tf[y]==1) flag=1;
			else ou=1,dfs(y,x);
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	memset(first,-1,sizeof(first));
	memset(ss,0,sizeof(ss));
	int x,y;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		if(x>y) swap(x,y);
		if(!f[x][y])
		{
			ss[x]++;ss[y]++;
		ins(x,y);ins(y,x);
		f[x][y]=1;
		}
		
	}
	for(int i=1;i<=n;i++)
	{
		if(ss[i]>2)
		{
			printf("0\n");
			return 0;
		}
	}long long ans=1;
	for(int i=1;i<=n;i++)
	{
		if(!tf[i])
		{
			flag=0;ou=0;
			dfs(i,0);
			if(flag==1)
			{
				printf("0\n");
				return 0;
			}
			cnt++;
			if(ou)ans=(ans*2)%mod;
		}
	}
	
	for(int i=1;i<=cnt;i++) ans=(long long)(ans*i)%mod;
	printf("%lld\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值