1. 程式人生 > >Usaco Training Section 5.3 Network of Schools

Usaco Training Section 5.3 Network of Schools

tarjan縮點模板題

首先tarjan縮點一下,然後第一問直接輸出入度為0的點的個數,因為這些點沒有點可以到達。第二問要特判一下,如果原圖已經是強連通分量,直接輸出0。否則輸出max(入度為0的點的個數,出度為0的點的個數),大概理解一下:這樣之後,每個強連通分量都能夠將檔案傳出去和傳入,好像就可以了。

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 2147483647
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;

inline int read(){
	int x=0;char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

const int M=10005,N=105;
struct edg{
	int nxt,to;
}e[M<<1];
int head[N],cnt;
stack<int> s;
bool vis[N];
int ind[N],low[N],inde;
int tot,num[N],sz[N];

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

inline void tarjan(int u){
	ind[u]=low[u]=++inde;
	s.push(u);
	vis[u]=1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(!ind[v]){
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],ind[v]);
		}
	}
	if(low[u]==ind[u]){
		++tot;
		int v=0;
		while(v!=u){
			v=s.top();
			s.pop();
			vis[v]=0;
			num[v]=tot;
			++sz[tot];
		}
	}
}

int ru[N],chu[N];
int main()
{
	freopen("schlnet.in","r",stdin);
	freopen("schlnet.out","w",stdout);
	int n=read();
	for(int i=1;i<=n;++i){
		int x=read();
		while(x!=0){
			add(i,x);
			x=read();
		}
	}
	tot=0;
	for(int i=1;i<=n;++i)
		if(!ind[i]) tarjan(i);
	if(tot==1){
		puts("1");
		puts("0");
		return 0;
	}
	for(int i=1;i<=n;++i)
		for(int j=head[i];j;j=e[j].nxt){
			int v=e[j].to;
			if(num[i]!=num[v]) ++ru[num[v]],++chu[num[i]];
		}
	int ru0=0,chu0=0;
	for(int i=1;i<=tot;++i){
		if(ru[i]==0) ++ru0;
		if(chu[i]==0) ++chu0;
	}
	printf("%d\n%d\n",ru0,max(ru0,chu0));
	return 0; 
}