【ac梦工厂】拓扑排序 hdu2647

题目链接https://vjudge.net/contest/151613#problem/C


题意:给你n个点,有m个要求,要求中有两个数,表示第一个点的值要大于第二点的值。拓扑排序。

代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

pair<int ,int>p;
vector<int>g[10005];
int degree[10005];
long long topo(int n)
{
    long long ans=0;
    queue<pair<int,int> > q;
    int tot=0;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            p.first=i,p.second=888;
            q.push(p);
        }
    }
    while(q.size())
    {
        pair<int,int>qq=q.front();
        q.pop();
        tot++;
        ans+=qq.second;
        for(int j=0;j<g[qq.first].size();j++)
        {
            degree[g[qq.first][j]]--;
            if(degree[g[qq.first][j]]==0)
            {
                p.second=qq.second+1;
                p.first=g[qq.first][j];
                q.push(p);
            }
        }
    }
    if(tot==n)
        return ans;
    else
        return 0;
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(degree,0,sizeof(degree));
        memset(g,0,sizeof g);
        for(int i=0;i<m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            degree[a]++;
            g[b].push_back(a);
        }
        long long an=topo(n);
        if(an==0)
            puts("-1");
        else
            printf("%lld\n",an);
    }
    return 0;
}

这一题跟前面的A、B题略有不同。需要知道每个节点的出度是多少,因为出度的值会影响这个点的值,所以需要用pair去保存这个点和这个点的值,最后加起来就可以了


从出度为0的点开始操作,然后将相连点中出度为0的压入队列中,点值+1即可。


topo一般模版:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

vector<TYPE>g[MAX_N];                  //TYPE可以根据需要进行修改
int degree[MAX_N];

int topo(int n)
{
    queue<TYPE>q;
    memset(degree,0,sizeof(degree));   //注意初始化
    for(int i=0;i<n;i++)               //注意数据的给法是从0开始还是1开始
    {
        for(int j=0;j<g[i].size();j++)
        {
            degree[g[i][j]]++;
        }
    }
    for(int i=0;i<n;i++)               //注意数据的给法是从0开始还是1开始
    {
        if(degree[i]==0)
        {
            q.push(i);
        }
    }
    int tot=0;
    while(q.size())
    {
        int qq=q.front();                  //根据类型修改qq的类型
        q.pop();
        tot++;
        for(int i=0;i<g[qq].size();i++)
        {
            degree[g[qq][i]]--;
            if(degree[g[qq][i]]==0)
                q.push(g[qq][i]);
        }
    }
    if(tot==n)                           //判断自环
        return 1;
    else
        return 0;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(g,0,sizeof(g));
        int a,b;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            g[a].push_back(b);                 //根据TYPE的类型和出度入度的不同,这里会有所不同
        }
        if(topo(n))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值