再讲Floyd变形:传递闭包类问题

题目

今天上课老师讲到一道传递闭包的问题,由于蒟蒻之前讲的不详细再来讲一遍。
传送门

思路

  1. 建图,注意是有向图。
  2. 能确定名次指的是:在图上由这个点可以到达的点数+在图上可以到达这个点的点数=n-1
  3. 对图跑一遍传递闭包(floyd变形)
  4. 按2的思路进行统计,输出答案

代码及解析

#include<bits/stdc++.h>
using namespace std;
int read(){
	int x=0;
	char c=getchar();
	while(c>'9'||c<'0'){
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+(c^'0');
		c=getchar();
	}
	return x;
}//快读
int n,m,a,b;//如题目中的意义
bool dis[101][101];//由于是传递闭包,我们定义成bool就可以了
int main(){
	n=read();
	m=read();
	for(int i=1;i<=m;i++){
		a=read();
		b=read();
		dis[a][b]=1;//注意,是有向图所以我们只搞一个边
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dis[i][j]=dis[i][j]||(dis[i][k]&&dis[k][j]);//核心代码,逻辑很简单
			}
		}
	}
	int cnt=0;
	for(int i=1;i<=n;i++){
		int tot=0;
		for(int j=1;j<=n;j++){
			tot+=dis[i][j];
		}
		for(int j=1;j<=n;j++){
			tot+=dis[j][i];
		}//以上统计点的个数
		if(tot==n-1)cnt++;//符合条件就统计
	}
	cout<<cnt;//输出
	return 0;
}
posted @ 2023-01-08 17:37  MornHus  阅读(40)  评论(0)    收藏  举报