传递闭包
Description
已知有n头牛,m次战斗关系,询问最终可以确定排名的牛的数量。
Input
多组测试数据,对于每组测试数据,第1行输入两个整数n(1 <= n <= 100)和m(0 <= m <= 4950),分别表示有n头牛和m次战斗关系,之后m行每行输入两个正整数x和y表示编号为x的牛可以战胜编号为y的牛,数据保证合法,询问可以确定排名的牛的数量。
Output
对于每组测试数据,输出整数ans,表示可以确定排名的牛的数量。
Sample
Input
5 5
4 3
4 2
3 2
1 2
2 5
Output
2
这一道题目是比较有意思的,作为离散数学学到的知识,还是很惊讶于它和自己现阶段所需要的算法竟然能这么吻合,很舒服,虽然自己不能说完全掌握但是时间会告诉我们答案。
对于闭包w的了解还不是很多,之后会再总结。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
int a[110][110];//用一个数组来表示是否可以判定两者之间的战斗关系
int ans=0,n,m;
void warshall()
{
for(int i=1; i<=n; i++)//n次循环
{
for(int j=1; j<=n; j++)//每一次循环中两牛的战斗情况
{
if(a[j][i]==1)
for(int k=1; k<=n; k++)
{
a[j][k]=a[j][k]+a[i][k];//如果
if(a[j][k]>1)
{
a[j][k]=1;
}
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
ans=0;
memset(a,0,sizeof(a));//初始化数组a,0为无战斗关系,1为有战斗关系
for(int i=0; i<m; i++)
{
int v,u;
scanf("%d %d",&v,&u);
a[v][u]=1;//表示v可以战胜u
}
warshall();//这是本题最重要的部分,闭包解释:判断两者之间关系
int flag=1;//flag标志
for(int i=1; i<=n; i++)
{
flag=1;
for(int j=1; j<=n; j++)
{
if(i==j)//这个过程的目的有着想要将i==j的情况剔除,只去判定正确战斗情况
{
if(a[i][j]==1)
{
flag=0;
break; //如果自己和自己有战斗则数据错误,无法判定
}
}
else if(a[i][j]==0&&a[j][i]==0)//如果i和j无任何战斗关系
{
flag=0;
break;//无法判定退出
}
}
if(flag==1)
ans++;//可以判定的牛的情况ans+1
}
printf("%d\n",ans);
}
}