HDU2647 Reward【拓扑排序】

Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12569    Accepted Submission(s): 4033


 

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

 

Author

dandelion

 

Source

曾是惊鸿照影来

问题链接HDU2647 Reward

问题简述:(略)

问题分析

  给定n个人及其m种关系,工厂主给n个工人发奖金,m种关系是有工人要求比别的工人奖金多一点(多1元就可以),需要计算满足条件时输出总共需要发的奖金数,不能满足时则输出-1。

  这种工人之间的关系形成的图有循环的话,就无法满足条件,输出-1。

  这个问题可以用拓扑排序的方法来解决,如果可以进行排序则可以计算发放奖金的总数。

  节点规模虽然比较小,图也可以用采用邻接表来表示。

程序说明

  没有前驱的节点,可以排序输出,放入队列中,并且做个遍历标记。再用队列中的节点(已经可以输出)去除与其有边相连节点的前驱,直到不能操作为止。如果节点全部遍历,则没有循环即合法,否则不合法。是否遍历全部节点,计数一下就可以了。

  使用数组add[]存储要求比别人高的奖金,最少多1元。

题记:(略)

参考链接:(略)

AC的C++语言程序如下:

/* HDU2647 Reward */

#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
#include <string.h>

using namespace std;

const int N = 1e4;
vector< vector<int> > g;
int din[N + 1], add[N + 1];
int n, m;

int toposort()
{
    queue<int> q;
    for(int i = 1; i <= n; i++)
        if(din[i] == 0)
            q.push(i);

    int cnt = 0;
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        cnt++;

        for(int i = 0; i < (int)g[u].size(); i++) {
            int v = g[u][i];
            if(--din[v] == 0) {
                q.push(v);
                add[v] = max(add[u] + 1, add[v]);
            }
        }
    }

    if(cnt != n)
        return -1;
    else {
        int total = 888 * n;
        for(int i = 1; i <= n; i++)
            total += add[i];
        return total;
    }
}

int main()
{
    while(~scanf("%d%d", &n, &m)) {
        g.clear();      // 图邻接矩阵
        g.resize(n + 1);
        memset(din, 0, sizeof(din));    // 节点入度
        memset(add, 0, sizeof(add));

        // 读入图
        for(int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            g[v].push_back(u);
            din[u]++;
        }

        // 输出结果
        printf("%d\n", toposort());
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/81266855