传递闭包

传递闭包

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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pig2687

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值