codevs 1019 集合论与图论

*PS:所以以后加不加特判还是要相信自己的直觉??我就知道(눈‸눈)。。。

go to the problem

题目描述 Description

集合论与图论对于小松来说是比数字逻辑轻松,比数据结构难的一门专业必修课。虽然小松在高中的时候已经自学过了离散数学中的图论,组合,群论等知识。但对于集合论,小松还是比较陌生的。集合论的好多东西也涉及到了图论的知识。

在第四讲的学习中,小松学到了“有序对”这么一个概念,即用< x, y >表示有序对x和y。要注意的是有序对< x, y >不等于有序对< y, x >。对于一个有序对集合R={< x,y >, < y, z >, < x, z >,……},我们说R是传递的,当且仅当他满足下面的性质:

这里写图片描述

红色字体用直观的语言描述是:如果存在< x, y >∈R,< y, z >∈R,那么一定存在< x, z >∈R。

这里集合R可以对应到一个有向图G,有序对< x ,y >对应到了G中的一条有向边。 你现在的任务是,对于任意给定的一个简单有向图G(同一有向边不出现两次),判断G是否具有传递性。

输入描述 Input Description

   输入文件set.in第一行包含测试数据的个数T(1<=T<=10)。接下来T组测试数据,每组测试数据第一行包含两个个整数n和m(1<=n<=1000, n<=m<=100000),表示G中元素个数和有向边的个数,接下来的m行每行2个整数x, y(1<=x,y<=n)表示x与y之间有一条有向边连接。

输出描述 Output Description

   对于每组数据,如果G是传递的,你需要向输出文件set.out输出一行”Yes”, 否则输出一行”No”。

样例输入 Sample Input

2

3 3

1 2

1 3

2 3

4 5

1 2

1 3

1 4

2 3

3 4

样例输出 Sample Output

Yes

No

数据范围及提示 Data Size & Hint

有30%满足1<=n<=100, 1<=m<=10000;

有100%的数据满足1<=n<=1000, 1<=m<=100000;

lalala

这是一道图论(大水)题呢。emmm倒是没有什么算法,我看题解上有直接暴力的、有用floyd的、有递归的、有模拟的…我用的bfs做的2333。

方法:枚举每个点,判断从这个点到的没遍历的点的最短距离如果>=2就return false。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int T,n,m,f;
int de[1010];
int first[1010],next[100010],q[1010];
bool used[1010];
struct maple{
    int f,t;
}Rode[100010];

bool bfs(int x)
{
    int head=0,tail=1;
    memset(de,0,sizeof(de));
    memset(used,0,sizeof(used));
    q[tail]=x;
    used[x]=1;
    while(head<tail)
    {
        ++head;
        for(int i=first[q[head]];i;i=next[i])
           if(!used[Rode[i].t])
           {
               used[Rode[i].t]=1;
               de[Rode[i].t]=de[q[head]]+1;
               q[++tail]=Rode[i].t;
               if(de[Rode[i].t]>=2) return false;
           }
    }
    return true;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        f=0;
        scanf("%d%d",&n,&m);
        memset(first,0,sizeof(first));
        memset(next,0,sizeof(next));
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&Rode[i].f,&Rode[i].t);
            next[i]=first[Rode[i].f];
            first[Rode[i].f]=i;
        }
        for(int i=1;i<=n;++i)
          if(!bfs(i))
          {
             f=1;break;
          } 
        if(f) printf("No\n");
        else printf("Yes\n"); 
    }  
    return 0;   
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值