Luogu P2746 [USACO5.3] Network of Schools (abbreviated)

Topic link

The first question of this question is indeed very template, but the second question is not that simple. After reading many questions, I directly post the conclusion, even if there is an explanation, it is extremely brief. Write a more detailed article here.

First, shrink the original image to form a DAG composed of several connected blocks.

We first consider the case of a single connected block:
it is obviously the maximum value of the number of points with zero out-degree and zero in-degree, because one edge can give two (one in-degree is zero and out-degree is zero) points make a contribution.
In this way, no matter where you start, you can go to an end point xxx (the degree of out is zero), and thus go to one andxxAn initial point where x is connected (in-degree is zero). Next, because you are at an initial point, you can go to all the end points in the connected block. And because all the end points are connected to the initial point, you can reach any point in the connected block, which forms a strong connected component.

Then, the same is true when there are more connected blocks. We have kkk connected blocks,iii connected blocks areai a_iai. Then, for each iii I amai a_iaiThe end point of is connected to ai + 1 a_{i+1} according to the above methodai+1The initial point. In particular, will ak a_kakThe end point of is connected to a 1 a_1a1The outgoing endpoint.
In this way, each ai a_iaiBoth end points can reach ai + 1 a_{i+1}ai+1The initial point of to reach ai + 1 a_{i+1}ai+1 The end points of, also form a strong connected component.

Finally, the answer to the second question is the maximum value of the number of end points and the number of initial points in the whole picture (after shrinking)

#include<cstdio> 
#include<iostream>
#include<vector>
const int Maxn=100+10,inf=0x3f3f3f3f;
int n,timecnt,cnt; // 一年前写的代码,很丑,仅供参考
int dis[Maxn],ind[Maxn];
int dfn[Maxn],low[Maxn],f[Maxn];
bool vis[Maxn];
std::vector <int> e[Maxn],g[Maxn];
struct _stack{
    
    
	int s[Maxn],tot=0;
	inline int size(){
    
    return tot;}
	inline int top(){
    
    return s[tot];}
	inline void push(int x){
    
    s[++tot]=x;}
	inline void pop(){
    
    s[tot--]=0;}
};
_stack stack;
int read()
{
    
    
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=s*10+ch-'0',ch=getchar();
	return s*w;
}
void tarjan(int x)
{
    
    
	dfn[x]=low[x]=++timecnt;
	stack.push(x),vis[x]=1;
	for(int i=0;i<e[x].size();++i)
	{
    
    
		int y=e[x][i];
		if(!dfn[y])
		{
    
    
			tarjan(y);
			low[x]=std::min(low[x],low[y]);
		}
		else if(vis[y])low[x]=std::min(low[x],low[y]);
	}
	if(dfn[x]==low[x])
	{
    
    
		while(stack.size())
		{
    
    
			int y=stack.top();
			stack.pop();
			f[y]=x,vis[y]=0;
			if(y==x)break;
		}
	}
}
int main()
{
    
    
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	n=read();
	for(int x=1;x<=n;++x)
	{
    
    
		int y=read();
		while(y)
		{
    
    
			e[x].push_back(y);
			y=read();
		}
	}
	for(int i=1;i<=n;++i)
	if(!dfn[i])tarjan(i);
	for(int i=1;i<=n;++i)
	{
    
    
		for(int j=0;j<e[i].size();++j)
		{
    
    
			int x=i,y=e[i][j];
			if(f[x]==f[y])continue;
			g[f[x]].push_back(f[y]);
			ind[f[y]]++;
		}
	}
	int cnt1=0,cnt2=0;
	for(int i=1;i<=n;++i)
	{
    
    
		if(f[i]!=i)continue;
		cnt++;
		if(!g[i].size())cnt1++;
		if(!ind[i])cnt2++;
	}
	if(cnt==1)
	{
    
    
		printf("1\n0\n");
		return 0;
	}
	printf("%d\n%d\n",cnt2,std::max(cnt1,cnt2));
	return 0;
}

Guess you like

Origin blog.csdn.net/Brian_Pan_/article/details/108216618