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; } } }