HDU 2467 Reward(逆拓扑排序)

拓扑排序的变形,逆序建图就好了

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3951    Accepted Submission(s): 1203

Problem Description

Dandelion‘s uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards.

The workers will compare their rewards ,and some one may have demands of the distributing of rewards ,just like a‘s reward should more than b‘s.Dandelion‘s unclue wants to fulfill all the demands, of course ,he wants to use the least money.Every work‘s reward
will be at least 888 , because it‘s a lucky number.

Input

One line with two integers n and m ,stands for the number of works and the number of demands .(n<=10000,m<=20000)

then m lines ,each line contains two integers a and b ,stands for a‘s reward should be more than b‘s.

Output

For every case ,print the least money dandelion ‘s uncle needs to distribute .If it‘s impossible to fulfill all the works‘ demands ,print -1.

Sample Input

2 1
1 2
2 2
1 2
2 1

Sample Output

普通拓扑排序

1777
-1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
const int INF = 1e6;
const int ma = 1010;
#define MAX 0x3f3f3f3f
using namespace std;
struct node{
    int u,v,next;
}g[20100];
int head[20100],n,m,rudu[10100],t;
int cost[10100];
//struct no{
//    int x,ans;
//    friend bool operator < (const no &a,const no &b)
//    {
//        return a.ans>b.ans;
//    }
//};
void add(int a,int b)
{
    g[t].u = a;
    g[t].v = b;
    g[t].next = head[a];
    head[a] = t++;
}
int l;
bool vis[10010];
void TOP()
{
    //priority_queue<no>q;
    l = 0;
   // no f,t;
    memset(vis,0,sizeof(vis));
    for(int i = 1;i<=n;i++)
        cost[i] = 888;
        int sum = 0;
        int flag = 1;
        for(int i = 1;i<=n;i++)
        {
            for(int j = 1;j<=n;j++)
            {
                if(rudu[j]==0)
                {
                    rudu[j]--;
                    l++;
                    sum+=cost[j];
                    for(int k = head[j];k!=0;k = g[k].next)
                    {
                        rudu[g[k].v]--;
                        if(cost[g[k].v] < cost[j]+1) //这句不能少,要判断当前连接的点有没有被其他的点+1过,加过则不加
                        cost[g[k].v] = cost[j]+1;
                    }
                }
            }
        }
//printf("l = %d\n",l);
       if(l==n)
        printf("%d\n",sum);
       else
        puts("-1");

}
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        memset(rudu,0,sizeof(rudu));
        memset(head,0,sizeof(head));
        t = 1;
        for(int i = 0;i<m;i++)
        {
             scanf("%d%d",&a,&b);
             add(b,a);
        rudu[a]++;
        }
        TOP();
    }
    return 0;
}

队列形式的拓扑排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
const int INF = 1e6;
const int ma = 1010;
#define MAX 0x3f3f3f3f
using namespace std;
struct node{
    int u,v,next;
}g[50000];
int head[50100],n,m,rudu[10100],t;
struct no{
    int x,ans;
};
void add(int a,int b)
{
    g[t].u = a;
    g[t].v = b;
    g[t].next = head[a];
    head[a] = t++;
}
int aa[1100],l;
void TOP()
{
    queue<no>q;
    l = 0;
    no f,t;
    t.ans = 888;
    bool vis[10010];
    memset(vis,0,sizeof(vis));
    long long sum = 0;
        for(int j = 1;j<=n;j++)
        {
            if(rudu[j]==0 && !vis[j])
            {
                rudu[j]--;
                vis[j] = 1;
                l++;
                t.x = j;
                q.push(t);
            }
        }
        while(!q.empty())
        {
            f = q.front();
            q.pop();
            sum += f.ans;
            if(!head[f.x]) continue;
            for(int i = head[f.x];i!=0;i = g[i].next)
            {
                rudu[g[i].v]--;
                if(rudu[g[i].v]==0 && !vis[g[i].v])
                {
                    l++;
                    if(t.ans<f.ans+1)
                    t.ans = f.ans+1;
                    t.x = g[i].v;
                    q.push(t);
                    vis[t.x] = 1;
                }
            }
        }
//printf("l = %d\n",l);
       if(l==n)
        cout<<sum<<endl;
       else
        puts("-1");

}
int main()
{
    int a,b;
    while(~scanf("%d%d",&n,&m))
    {
        memset(rudu,0,sizeof(rudu));
        memset(head,0,sizeof(head));
        t = 1;
        for(int i = 0;i<m;i++)
        {
             scanf("%d%d",&a,&b);
             add(b,a);
        rudu[a]++;
        }
           TOP();
    }
    return 0;
}

HDU 2467 Reward(逆拓扑排序)

时间: 2024-08-07 04:14:37

HDU 2467 Reward(逆拓扑排序)的相关文章

HDU 2647 Reward【拓扑排序】

题意:工厂发工资,最低工资是888元,然后比他高一层得人的工资是889,依次类推 因为是从工资低的人推到工资高的人,所以反向建图 然后就是自己写的时候犯的错误,以为工资是后一个人比前一个人高1元,然后就直接判断是否能形成拓扑序列之后,用n*888+(n-1)*n/2来算了 这样不对,是后一层的工资比前一层得工资多1元,用一个数组记录下来钱就可以了 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4

hdu 2647 Reward(拓扑排序,反着来)

Reward Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 51   Accepted Submission(s) : 21 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description Dandelion's uncle is a boss of

hdu 2647 Reward(拓扑排序)

1.反向建图,有利于计算 2.代码: #include<cstdio> #include<cstring> #include<stdlib.h> #define Max(a,b) ((a)>(b)?(a):(b)) using namespace std; typedef struct ArcNode { int adjvex; struct ArcNode * nextarc; } ArcNode; typedef struct VNode { int vert

HDOJ 2647 Reward 【逆拓扑排序+分层】

题意:每一个人的基础工资是888. 因为一部分人要显示自己水平比較高,要求发的工资要比其它人中的一个人多.问你能不能满足他们的要求,假设能的话终于一共要发多少钱,假设不能就输出-1. 策略:拓扑排序. 这道题有些难点:一:数据大,建二维数组肯定不行,要换其它的数据结构(vector, 或者是链式前向星(本题代码用的是链式前向星)): 二:要逆拓扑排序(就是将++in[b]换成++in[a]). 三要分层次(依据上一个的钱数+1就可以). 不懂什么是链式前向星 移步:http://blog.csd

hdu 4857 逃生 (拓扑排序+保证最小在前面)

逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 74    Accepted Submission(s): 13 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前. 同时,社会是不平

HDU2647 Reward 【拓扑排序】

Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3927    Accepted Submission(s): 1199 Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he w

HDU 4324:Triangle LOVE( 拓扑排序 )

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2271    Accepted Submission(s): 946 Problem Description Recently, scientists find that there is love between any of two people. For

HDU 4857 (反向拓扑排序 + 优先队列)

题意:有N个人,M个优先级a,b表示a优先于b,并且每个人有个编号的优先级,输出顺序. 思路来自:与PKU3687一样 在基本的拓扑排序的基础上又增加了一个要求:编号最小的节点要尽量排在前面:在满足上一个条件的基础上,编号第二小的节点要尽量排在前面:在满足前两个条件的基础上,编号第三小的节点要尽量排在前面--依此类推.(注意,这和字典序是两回事,不可以混淆.) 如图 1 所示,满足要求的拓扑序应该是:6 4 1 3 9 2 5 7 8 0. 图 1 一个拓扑排序的例子 一般来说,在一个有向无环图

hdu 4857 逃生(拓扑排序逆序 + 优先队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 题意:有编号 1 - n 的 n 个人逃生,编号越小的人越有钱, 在满足 m 个前提的条件下要尽可能早的逃脱 .m个前提,对于每个前提 a , b,代表 a 要早于 b逃脱. 思路: (1)这题可以理解为有钱的人优先级越高,所以可以用优先队列. (2)但是要注意这道题和字典序升序的区别. eg:5 1 5 1 按照字典序的答案:2 3 4 5 1,    本题答案: 5 1 2 3 4. 因为