HDU 2647 Reward (拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2647

 

题意是给你n点m条有向边,叶子点(出度为0)上的值为888,父亲点为888+1,依次计算... 让你求最小的值,但是中间出现有向环就不行了,输出-1。

 

拓扑排序队列实现,因为叶子是最小的,所以把边反向就可以求了。

//拓扑队列实现
//就是先把入度为0的先入队,然后每次出队的时候把相邻的点的入度减1,要是入度为0则再入队,不断循环直到队列为空
//时间复杂度为O(N + E)
//这题就是把边反向就好了
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN = 1e4 + 5;
typedef pair <int , int> P;
vector <int> G[MAXN];
int du[MAXN];
int main()
{
    int n , m , u , v;
    while(~scanf("%d %d" , &n , &m)) {
        for(int i = 1 ; i <= n ; i++) {
            G[i].clear();
            du[i] = 0;
        }
        for(int i = 0 ; i < m ; i++) {
            scanf("%d %d" , &u , &v);
            G[v].push_back(u);
            du[u]++;
        }
        queue <P> que;
        while(!que.empty()) {
            que.pop();
        }
        int cont = 0 , res = 0;
        for(int i = 1 ; i <= n ; i++) {
            if(!du[i]) {
                que.push(P(i , 888));
                res += 888;
                cont++;
            }
        }
        while(!que.empty()) {
            P temp = que.front();
            que.pop();
            for(int i = 0 ; i < G[temp.first].size() ; i++) {
                du[G[temp.first][i]]--;
                if(!du[G[temp.first][i]]) {
                    que.push(P(G[temp.first][i] , temp.second + 1));
                    res += temp.second + 1;
                    cont++;
                }
            }
        }
        if(cont == n) {
            cout << res << endl;
        }
        else {
            cout << -1 << endl;
        }
    }
}

 

posted @ 2016-03-13 14:35  Recoder  阅读(401)  评论(0编辑  收藏  举报