POJ 1236 Network of Schools 強連通分量

~hsm~發表於2019-03-09

titlep1234

POJ 1236
CH POJ1236
LUOGU 2812 加強版
LUOGU 2746 普通版

code

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
const int maxm=5e6+6;
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1,ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}
int spot[maxm],ver[maxm],Next[maxm],head[maxn],len=0;
void add(int x,int y)
{
	spot[++len]=x,ver[len]=y,Next[len]=head[x],head[x]=len;
}
int Stack[maxn],top=0;
int dfn[maxn],low[maxn],id=0;
int belong[maxn],siz[maxn],tot=0;
bool instack[maxn];
void tarjan(int x)
{
	dfn[x]=low[x]=++id;//存自己的時間和
	instack[x]=1;
	Stack[++top]=x;
	for (int i=head[x],y;i;i=Next[i])
		if (!dfn[y=ver[i]])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if (instack[y])//如果在別的聯通塊就不管了
			low[x]=min(low[x],dfn[y]);
	int k;
	if (dfn[x]==low[x])//自己是自己的祖先(也就是掃不到時間更早的點了)
	{
		tot++;
		do
		{
			k=Stack[top];
			++siz[tot];
			--top;
			instack[k]=0;
			belong[k]=tot;
		}while (k!=x);
	}
}
int n,m,a,ans1=0,ans2=0,In[maxn],Out[maxn];
int main()
{
	read(n);
	for (int i=1;i<=n;++i)
		while (1)
		{
			read(a);
			if (!a) break;
			++m;
			add(i,a);
		}
	memset(instack,0,sizeof(instack));
	for (int i=1;i<=n;++i)
		if (!dfn[i]) tarjan(i);//並不一定是個連通圖
	for (int i=1,x,y;i<=m;++i)
		if (belong[x=spot[i]]!=belong[y=ver[i]])//自己圖內不管
			++In[belong[y]],//y的入度+1
			++Out[belong[x]];//x的出度+1
	for (int i=1;i<=tot;++i)//統計出度入度為0的點的出現次數
	{
		if (!In[i]) ++ans1;
		if (!Out[i]) ++ans2;
	}
	ans2=max(ans1,ans2);//****第二問,所有點要出度不為0而且入度不為0
	if (tot==1) ans1=1,ans2=0;//****嗯要特判
	printf("%d\n%d",ans1,ans2);
	return 0;
}

相關文章