【CF1394B】Boboniu Walks on Graph【图论】【集合哈希】

题意:给定 n n n个点 m m m张图的有向图,有 1 ∼ m 1\sim m 1m互不相同每个点出度不超过 k k k。对于一个 k k k元组 c i c_i ci,图中的每个点 u u u只保留第 c d e g u c_{deg_u} cdegu小的边。求有多少种 c c c使得在保留下来的图中每个点沿着出边一直往下走可以走回自己。

n , m ≤ 2 × 1 0 5 , k ≤ 9 n,m\leq 2\times 10^5,k\leq 9 n,m2×105,k9

显然直接 k ! k! k!暴力枚举方案,问题在于如何快速判断。

不难看出题中的条件等价于每个点入度恰好为 1 1 1

也相当于每条边的终点恰好遍历 1 ∼ n 1 \sim n 1n

写个哈希就完了

复杂度 O ( n + k ! ) O(n+k!) O(n+k!)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
#include <utility>
#include <cstdlib>
#include <ctime>
#define MAXN 200005
using namespace std;
int u[MAXN],v[MAXN],n,m,k;
typedef pair<int,int> pi;
vector<int> e[MAXN];
vector<pi> lis[MAXN]; 
inline int id(const pi& p){return p.first*(p.first-1)/2+p.second;}
int ans[10],key[MAXN],val[10][10],rt,cnt;
void check()
{
	int t=0;
	for (int i=1;i<=k;i++) t+=val[i][ans[i]];
	if (t==rt) ++cnt;
}
void dfs(int i)
{
	if (i>k) return check();
	for (ans[i]=1;ans[i]<=i;ans[i]++) dfs(i+1);
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=n;i++) rt+=(key[i]=rand());
	for (int i=1;i<=m;i++)
	{
		int x,y,w;
		scanf("%d%d%d",&x,&y,&w);
		u[w]=x,v[w]=y;
	}
	for (int i=1;i<=m;i++)	e[u[i]].push_back(v[i]);
	for (int u=1;u<=n;u++)
		for (int i=0;i<(int)e[u].size();i++)
			val[e[u].size()][i+1]+=key[e[u][i]];
	dfs(1);
	cout<<cnt;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值