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 @   Recoder  阅读(402)  评论(0编辑  收藏  举报
编辑推荐:
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
阅读排行:
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· 用99元买的服务器搭一套CI/CD系统
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· Excel百万数据如何快速导入?
· ShadowSql之.net sql拼写神器
点击右上角即可分享
微信分享提示