codeforces 859E Desk Disorder

本文针对一组人员现有的座位和候选座位,提出了一种有效的方法来计算所有合法的座位安排方案数。通过对不同类型的连通子图进行分类讨论,包括带环、带自环和树状结构,得出了每种情况下方案数的计算公式。

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

        题意:每一个人有现有的位置x[i],以及候选的位置y[i],每个人可以选择坐到现有的位置以及候选的位置,要求每个位置最多坐一个人,求合法的方案数。

        我们将每一个x[i]与y[i]连一条边,那么我们可以将得到的图分成三种情况,带环的,带自环的,一棵树。

        首先,我们可以证明带环的联通子图最多带一个环,因为一条边象征着一个人,一个点代表着一个座位,如果两个环的话就会出现n个点m+1条边,由于起始座位不会相同,所以有一个人会没有起始座位所以说是不合法的。对于带环的情况,我们考虑一个人,如果他坐了自己的现有位置,那么其他人n-1个人位置便固定了,所以它有两种不同的位置,所以对于有环的情况,答案就是2种。

        接着考虑到带自环的情况,其实就是有环的特殊情况,相当于一个人座位一已经固定了, 其他人选的位置也就随之固定了,因为一样不会出现多环,所以答案是1种。

       最复杂的是一个树的情况,我们可以首先从链的情况入手,如果是两个点一条边,那么它的答案就是2,这个人可以坐任何一边,如果是三个点两条边的链,如下图


       如果1号人选了左边的a点,那么2号人就出现了像之前叙述的情况,共有两种情况,如果1号人选了b点,那么另外一个人选的点就固定了,那么a点的答案就是1+b点的答案,以此类推,对于一条链就是cnt[i]=cnt[i-1]+1。

      我们将这种链的情况推广的树上,那么就是从根开始,如果第一条边选了向叶子的方向,那么其他点方案固定,如果选了最顶的方向,其他下面便不是固定的了,就是加上cnt[叶子节点的方案数],推一下发现答案就是一棵树的节点个数。所以树的答案就是树的节点个数。

      由于各个联通子图相互独立,所以各个联通子图的答案相乘即为最终答案。

      下附AC代码。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 1000005
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int n;
int fa[maxn],huan[maxn],zihuan[maxn],siz[maxn];
int find(int now)
{
	return fa[now]==now ? now : fa[now]=find(fa[now]);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=2*n;i++)
	{
		fa[i]=i;
		siz[i]=1;
	}
	for(int i=1;i<=n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		
		int x1=find(x),y1=find(y);
		
		if(x==y)
			zihuan[x1]=1;
		if(x1==y1)
			huan[y1]=1;
		fa[x1]=y1;
	}
	for(int i=1;i<=2*n;i++)
	{
		int x=find(i);
		if(x!=i)
		{
			siz[x]+=siz[i];
			huan[x]|=huan[i];
			zihuan[x]|=zihuan[i];
		}
	}
	ll ans=1;
	for(int i=1;i<=2*n;i++)
	{
		if(find(i)==i)
		{
			if(zihuan[i]) continue;
			else if(huan[i]) ans=(ans*2)%mod;
			else ans=(ans*siz[i])%mod;
		}
	}
	printf("%I64d\n",ans);
} 


### Codeforces 887E Problem Solution and Discussion The problem **887E - The Great Game** on Codeforces involves a strategic game between two players who take turns to perform operations under specific rules. To tackle this challenge effectively, understanding both dynamic programming (DP) techniques and bitwise manipulation is crucial. #### Dynamic Programming Approach One effective method to approach this problem utilizes DP with memoization. By defining `dp[i][j]` as the optimal result when starting from state `(i,j)` where `i` represents current position and `j` indicates some status flag related to previous moves: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = ...; // Define based on constraints int dp[MAXN][2]; // Function to calculate minimum steps using top-down DP int minSteps(int pos, bool prevMoveType) { if (pos >= N) return 0; if (dp[pos][prevMoveType] != -1) return dp[pos][prevMoveType]; int res = INT_MAX; // Try all possible next positions and update 'res' for (...) { /* Logic here */ } dp[pos][prevMoveType] = res; return res; } ``` This code snippet outlines how one might structure a solution involving recursive calls combined with caching results through an array named `dp`. #### Bitwise Operations Insight Another critical aspect lies within efficiently handling large integers via bitwise operators instead of arithmetic ones whenever applicable. This optimization can significantly reduce computation time especially given tight limits often found in competitive coding challenges like those hosted by platforms such as Codeforces[^1]. For detailed discussions about similar problems or more insights into solving strategies specifically tailored towards contest preparation, visiting forums dedicated to algorithmic contests would be beneficial. Websites associated directly with Codeforces offer rich resources including editorials written after each round which provide comprehensive explanations alongside alternative approaches taken by successful contestants during live events. --related questions-- 1. What are common pitfalls encountered while implementing dynamic programming solutions? 2. How does bit manipulation improve performance in algorithms dealing with integer values? 3. Can you recommend any online communities focused on discussing competitive programming tactics? 4. Are there particular patterns that frequently appear across different levels of difficulty within Codeforces contests?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值