hdu2647 Reward 拓扑排序

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2647
题意是给n个人,m个x,y(x的钱要比y的钱多),每个人最少888,问最少要多少钱?
自己写老是想着dfs,结果dfs搜的头都晕了,还是不对。
应该是分层次的排,先排888,然后889,890。。。
先遍历找到所有入度为零且未标记的点,然后将这些点所连接的点的存一下,等遍历完,再将这些存的点的入度-1,这样就将这些点分成不同的层次,第一次为888,第二层为889,,,,,
还有就是判断环,如果是环的话,那么若入度为零且未标记的点的个数为零则说明为环。

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define printscanf freopen("intput.txt","r",stdin);
#define printprintf freopen("output.txt","w",stdout);
const int spot=10010;
const int edge=20010;
const int maxn=0;
const double pi=acos(-1.0);
int n,m,head[spot],sizes=0,sum[spot],ord[spot];
bool flag[spot];
struct stu
{
    int to,next;
} a[edge];
void init()
{
    memset(flag,0,sizeof(flag));
    memset(sum,0,sizeof(sum));
    memset(head,-1,sizeof(head));
    sizes=0;
}
void add_edge(int x,int y)
{
    a[sizes].to=y;
    a[sizes].next=head[x];
    head[x]=sizes++;
}
int tp_sort()
{
    int ans=0,i,j,dep=0,k,v,length=0;
    for(;;)
    {
        k=0;
        for(i=1; i<=n; i++)
        {
            if(!flag[i]&&!sum[i])   //若入度为零且未标记
            {
                ans+=dep+888,length++,flag[i]=1;  //dep表示第几层
                for(j=head[i]; j+1; j=a[j].next)
                {
                    v=a[j].to;
                    ord[++k]=v;   //将与入度为零的点连接的点存起来
                }
            }
        }
        if(length==n) return ans;
        if(!k) return -1;  //若入度为零的点无,则说明有环的存在
        for(i=1; i<=k; i++)
            sum[ord[i]]--;   //这些点入度-1
        dep++;  //层数+1
    }
}
int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        int x,y;
        for(i=1; i<=m; i++)
        {
            scanf("%d%d",&x,&y);  //建边是y->x
            add_edge(y,x);
            sum[x]++;
        }
        printf("%d\n",tp_sort());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值