hdu 3342 Legal or Not(判断成环)

本文探讨了一种使用拓扑排序解决复杂人际关系合法性的算法,通过实例分析和代码实现,详细解释了如何通过拓扑排序来判断人际关系网中是否存在环,从而决定其合法性。文章不仅提供了邻接矩阵和邻接表两种实现方式,还深入解析了算法背后的理论基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:hdu 3342 Legal or Not

题目大意:有n个人,m组关系(题目没有说没有重边,若用邻接矩阵,会被坑惨),<a,b>表示a是b的主人,若存在关系<a,b>,<b,c>,则<a,c>,也就是说a是b的主人,b是c的主人,那么a也是c的主人,这种关系是合法的,则输出YES,若a是b的主人,b是c的主人,c确是a的主人,那么这种关系不合法,则输出NO;

思路:这里主要判断是否能进行拓扑排序,若存在环,则不能进行拓扑排序,我们进行拓扑排序,会将每一个入度为0的点压入队列,若弹出点的个数刚好为n个,则说明能进行拓扑排序,反之若小于n,表明成环

1.邻接矩阵

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 1<<31-1
#define maxn 111
using namespace std;
int in[maxn],n,m,mapp[maxn][maxn];
int tuopu()
{
    int cnt  = 0;
    queue<int>q;
    for(int i=0;i<n;i++) if(!in[i]) q.push(i);
    while(!q.empty())
    {
        int a = q.front();
        q.pop();
        cnt++;
        for(int i=0;i<n;i++)
            if(mapp[a][i])
                if(!--in[i]) q.push(i);
    }
    if(cnt==n) return 1;
    return 0;
}
int main()
{
    while(cin>>n>>m,n+m)
    {
        fill(in,in+maxn,0);
        fill(&mapp[0][0],&mapp[maxn][0],0);
        while(m--)
        {
            int a,b;
            cin>>a>>b;
            if(!mapp[a][b])  mapp[a][b]=1,in[b]++;//注意,一大坑点,可能会有重边
        }
        int flag = tuopu();
        if(flag) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}
2.邻接表

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define maxn 111
using namespace std;
vector<int>G[maxn];
int in[maxn],n,m;
int tuopu()
{
    int cnt = 0;
    queue<int>q;
    for(int i=0;i<n;i++) if(!in[i]) q.push(i);
    while(!q.empty())
    {
        int temp = q.front();
        q.pop();
        cnt++;
        for(int i=0;i<G[temp].size();i++)
        {
            int a = G[temp][i];
            cout<<a<<endl;
            if(!--in[a]) q.push(a);
        }
    }
    if(cnt==n) return 1;
    return 0;
}
int main()
{
   int a,b;
   while(cin>>n>>m,n+m)
   {
       for(int i=0;i<n;i++) G[i].clear();
       fill(in,in+maxn,0);
       while(m--)
       {
           cin>>a>>b;
           G[a].push_back(b);
           in[b]++;
       }
       int flag = tuopu();
       if(flag) cout<<"YES"<<endl;
       else cout<<"NO"<<endl;
   }
   return 0;
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值