[ARC161F] Everywhere is Sparser than Whole (Judge)

发布时间 2023-06-02 22:41:14作者: 灰鲭鲨

Problem Statement

We define the density of a non-empty simple undirected graph as $\displaystyle\frac{(\text{number of edges})}{(\text{number of vertices})}$.

You are given positive integers $N$, $D$, and a simple undirected graph $G$ with $N$ vertices and $DN$ edges. The vertices of $G$ are numbered from $1$ to $N$, and the $i$-th edge connects vertex $A_i$ and vertex $B_i$. Determine whether $G$ satisfies the following condition.

Condition: Let $V$ be the vertex set of $G$. For any non-empty proper subset $X$ of $V$, the density of the induced subgraph of $G$ by $X$ is strictly less than $D$.

There are $T$ test cases to solve.

What is an induced subgraph?

For a vertex subset $X$ of graph $G$, the induced subgraph of $G$ by $X$ is the graph with vertex set $X$ and edge set containing all edges of $G$ that connect two vertices in $X$. In the above condition, note that we only consider vertex subsets that are neither empty nor the entire set.

Constraints

  • $T \geq 1$
  • $N \geq 1$
  • $D \geq 1$
  • The sum of $DN$ over the test cases in each input file is at most $5 \times 10^4$.
  • $1 \leq A_i < B_i \leq N \ \ (1 \leq i \leq DN)$
  • $(A_i, B_i) \neq (A_j, B_j) \ \ (1 \leq i < j \leq DN)$

Input

The input is given from Standard Input in the following format:

$T$
$\mathrm{case}_1$
$\mathrm{case}_2$
$\vdots$
$\mathrm{case}_T$

Each test case $\mathrm{case}_i \ (1 \leq i \leq T)$ is in the following format:

$N$ $D$
$A_1$ $B_1$
$A_2$ $B_2$
$\vdots$
$A_{DN}$ $B_{DN}$

Output

Print $T$ lines. The $i$-th line should contain Yes if the given graph $G$ for the $i$-th test case satisfies the condition, and No otherwise.


Sample Input 1

2
3 1
1 2
1 3
2 3
4 1
1 2
1 3
2 3
3 4

Sample Output 1

Yes
No
  • The first test case is the same as Sample Input 1 in Problem D, and it satisfies the condition.
  • For the second test case, the edge set of the induced subgraph by the non-empty proper subset $\{1, 2, 3\}$ of the vertex set $\{1, 2, 3, 4\}$ is $\{(1, 2), (1, 3), (2, 3)\}$, and its density is $\displaystyle\frac{3}{3} = 1 = D$. Therefore, this graph does not satisfy the condition.

新套路

要判定每个子图是否都满足这个要求,挺难弄的,但是移一下项。\(\frac mn<D,m<nD\),想到了 Hall定理

Hall定理内容:一个二分图存在满流,当且仅当对于任意一个左端点集 S,设 T 为所有和 S 有连边的店,那么 \(|T|\ge |S|\)

那么可以尝试构图,使得判断 \(m\) 是否小于等于 \(D\) 改为判断这个二分图是否存在满流。

把一个点拆成 \(D\) 个点,然后把每条边当成一个点,一条边 \((u,v)\)\(u\) 点拆出来的和 \(v\) 点拆出来的所有点连边。这样,这个二分图满流就代表所有的 \(m\le nD\)。直接跑网络流,可以不用真拆点,把一个点向汇点的流量调为 \(D\) 就行了。

但是我们还需要判断 \(m\) 是否等于 \(nD\),Editorial里写的结论是,给原图每条边定向。如果二分图中边 \(i\) 向点 \(u\) 流出,则从 \(u\) 连到点 \(v\),否则从 \(v\) 连向点 \(u\)。易得一个点出度为 \(D\)。如果得到的图是强连通的,那么条件成立。

如果有两个强连通分量,那么关注没有出度的那一个,由于他没有出度,所有所有的边都在强连通分块内,又因为每个点都有 \(D\) 条出边,所以他的密度等于 \(D\)

然后看是强连通分量的是不是一定满足要求,发现如果存在一个点集密度等于 \(D\),那么他没有出度,只能是整个强连通分量。

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5,T=(N<<1)-1;
int t,n,d,mxf,to[N],tme,idx,dfn[N],low[N],q[N<<1],v[N<<1],hd[N<<1],id[N],tp,st[N];
template<int N,int M>struct graph{
	int hd[N],e_num;
	struct edge{
		int u,v,nxt,f;
	}e[M<<1];
	void add_edge(int u,int v,int f)
	{
		e[++e_num]=(edge){u,v,hd[u],f};
		hd[u]=e_num;
		e[++e_num]=(edge){v,u,hd[v],0};
		hd[v]=e_num;
	}
	void clear()
	{
		for(int i=2;i<=e_num;i++)
			hd[e[i].u]=0;
		e_num=1;
	}
};
graph<N,N>g;
graph<N<<1,N<<2>fl;
int bfs()
{
	int l,r;
	for(int i=0;i<=n+n*d;i++)
		fl.hd[i]=hd[i],v[i]=0;
	fl.hd[T]=hd[T],v[T]=0;
	v[q[l=r=1]=0]=1;
	while(l<=r)
	{
		for(int i=fl.hd[q[l]];i;i=fl.e[i].nxt)
			if(fl.e[i].f&&!v[fl.e[i].v])
				v[q[++r]=fl.e[i].v]=v[q[l]]+1;
		++l;
	}
	return v[T];
}
int dfs(int x,int f)
{
	if(x==T)
		return f;
	for(int&i=fl.hd[x];i;i=fl.e[i].nxt)
	{
		int k;
		if(fl.e[i].f&&v[fl.e[i].v]==v[x]+1&&(k=dfs(fl.e[i].v,min(f,fl.e[i].f))))
		{
			fl.e[i].f-=k;
			fl.e[i^1].f+=k;
			return k;
		}
	}
	return 0;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++idx,st[++tp]=x;
	for(int i=g.hd[x];i;i=g.e[i].nxt)
	{
		if(g.e[i].f&&!dfn[g.e[i].v])
		{
			tarjan(g.e[i].v);
			low[x]=min(low[x],low[g.e[i].v]);
		}
		else if(g.e[i].f&&!id[g.e[i].f])
			low[x]=min(low[x],dfn[g.e[i].v]);
	}
	if(low[x]==dfn[x])
	{
		++tme;	
		while(st[tp]^x)
			id[st[tp--]]=tme;
		id[st[tp--]]=tme;
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		g.clear(),fl.clear();
		for(int i=0;i<=n*d;i++)
			dfn[i]=id[i]=0;
		idx=tme=mxf=tp=0;
		scanf("%d%d",&n,&d);
		for(int i=1,u,v;i<=n*d;i++)
		{
			scanf("%d%d",&u,&v);
			g.add_edge(u,v,0);
			fl.add_edge(0,i,1);
			fl.add_edge(i,n*d+u,1);
			to[i]=fl.e_num;
			fl.add_edge(i,n*d+v,1);
		}
		for(int i=1;i<=n;i++)
			fl.add_edge(i+n*d,T,d);
		for(int i=0;i<=n*d+n;i++)
			hd[i]=fl.hd[i];
		hd[T]=fl.hd[T];
		int k;
		while(bfs())
			while(k=dfs(0,2000000000))
				mxf+=k;
		if(mxf!=n*d)
		{
			puts("No");
			continue;
		}
		for(int i=1;i<=n*d;i++)
		{
			if(fl.e[to[i]].f)
				g.e[i<<1].f=1;
			else
				g.e[i<<1|1].f=1;
		}
		for(int i=1;i<=n;i++)
			if(!dfn[i])
				tarjan(i);
		puts(tme^1? "No":"Yes");
	}
}