[POI2011]KON-Conspiracy

After constructing the edges according to the 2-SAT model, two groups can be obtained: a clique and an independent set.
What needs to be considered afterwards is how many different schemes there are.
We found that for the group and independent collections, we can only take out one point each at a time and put it in the other side (of course we don’t need to take it). And since n just satisfies the data range of n^2, we enumerate the points taken from the group and put into the independent concentration, and the points taken from the independent set and put into the graph, n ^2 judges whether the operation is Can meet the conditions.
#include <bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int n;
bool f[N][N];
int tot1,tot2,in[N],out[N],a[N],b[N];
long long ans;
int now,top,col,dfn[N<<1],low[N<<1],sta[N<<1],color[N<<1];
int cnt,head[N<<1];
struct edge{
    
    int next,to;}e[N*N];

inline void add(int u,int v)
{
    
    
	cnt++;
	e[cnt].next=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}

void tarjan(int u)
{
    
    
	dfn[u]=low[u]=++now;
	sta[++top]=u;
	for (register int i=head[u]; i; i=e[i].next)
	{
    
    
		if (!dfn[e[i].to])
		{
    
    
			tarjan(e[i].to);
			low[u]=min(low[u],low[e[i].to]);
		}
		else if (!color[e[i].to]) low[u]=min(low[u],low[e[i].to]);
	}
	if (dfn[u]==low[u])
	{
    
    
		col++;
		while (sta[top]!=u) color[sta[top]]=col,top--;
		color[sta[top]]=col,top--;
	}
}

int main(){
    
    
	scanf("%d",&n);
	for (register int i=1; i<=n; ++i)
	{
    
    
		int x,now;
		scanf("%d",&x);
		while (x--)
		{
    
    
			scanf("%d",&now);
			f[i][now]=true;
		}
	}
	//i:在团内  i+n:在团外 
	for (register int i=1; i<=n; ++i)
	for (register int j=1; j<=n; ++j)
	if (i!=j)
	{
    
    
		if (f[i][j]) add(i+n,j);
		else add(i,j+n);
	}
	for (register int i=1; i<=2*n; ++i) if (!dfn[i]) tarjan(i);
	for (register int i=1; i<=n; ++i) if (color[i]==color[i+n]) {
    
    puts("0"); return 0;}
	
	for (register int i=1; i<=n; ++i) 
	if (color[i]<color[i+n]) in[++tot1]=i;
	else out[++tot2]=i;
	if (tot1 && tot2) ans=1;
	
	//for (register int i=1; i<=tot1; ++i) printf("%d ",in[i]); puts("");
	//for (register int i=1; i<=tot2; ++i) printf("%d ",out[i]); puts("");
	
	for (register int i=1; i<=tot1; ++i)
	{
    
    
		int hh=0;
		for (register int j=1; j<=tot2; ++j)
		{
    
    
			if (f[in[i]][out[j]])
			{
    
    
				if (hh==1) 
				{
    
    
					a[i]=1e9;
					break;
				}
				hh++;
				a[i]=out[j];
			}
		}
	}
	for (register int i=1; i<=tot2; ++i)
	{
    
    
		int hh=0;
		for (register int j=1; j<=tot1; ++j)
		{
    
    
			if (!f[out[i]][in[j]])
			{
    
    
				if (hh==1) 
				{
    
    
					b[i]=1e9;
					break;
				}
				hh++;
				b[i]=in[j];
			}
		}
	}
	if (tot1>1) 
	{
    
    
		for (register int i=1; i<=tot1; ++i) if (!a[i]) ans++;
	}
	if (tot2>1)
	{
    
    
		for (register int i=1; i<=tot2; ++i) if (!b[i]) ans++;
	}
	for (register int i=1; i<=tot1; ++i)
	for (register int j=1; j<=tot2; ++j)
	if ((!a[i] || a[i]==out[j]) && (!b[j] || b[j]==in[i])) ans++;
	printf("%lld\n",ans);
return 0;
}

Guess you like

Origin blog.csdn.net/Dove_xyh/article/details/108576623