[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");
	}
}