hdu 2647 Reward(拓撲排序+反圖)
阿新 • • 發佈:2018-04-11
nbsp style -- clu empty money sum 心態 基礎
題目鏈接:https://vjudge.net/contest/218427#problem/C
題目大意:
老板要給很多員工發獎金, 但是部分員工有個虛偽心態, 認為自己的獎金必須比某些人高才心理平衡; 但是老板很人道, 想滿足所有人的要求, 並且很吝嗇,想畫的錢最少
輸入若幹個關系
a b
a c
c b
意味著a 的工資必須比b的工資高 同時a 的工資比c高; c的工資比b高
當出現環的時候輸出-1
#include<iostream> #include<cstring> #include<queue> #include<cstdio> usingnamespace std; #define MAX 10005 int n, sum, ans; int into[MAX], head[MAX], money[MAX]; struct Reward { int to; int next; } edge[2 * MAX]; void topu() { int i, j, l, v; queue<int>Q; for (i = 1; i <= n; i++) if (into[i] == 0) Q.push(i);//把入度為0的點壓如隊列 while(!Q.empty()) { v = Q.front();//調用首位元素 sum += money[v]; Q.pop();//出隊 ans++; //用一個變量記錄調用元素的總量,最後與n作比較 for (l = head[v]; l != -1; l = edge[l].next)//與隊首元素v有關的都枚舉一遍 { if (--into[edge[l].to] == 0)//如果入度-1為0,即為v的下一個元素 { Q.push(edge[l].to);//將其壓入隊列 money[edge[l].to] = money[v] + 1;//保證後一個要比前一個多1 } } } } int main() { int m, a, b, tot; while (scanf("%d%d", &n, &m) != EOF) { memset(head, -1, sizeof(head)); memset(into, 0, sizeof(into)); for (int i = 1; i <= n; i++) money[i] = 888;//所有人一開始都為888 tot = 0; sum = 0; ans = 0; while (m--) { scanf("%d%d", &a, &b);//註意要逆過來,因為後一個b是基礎的888,應當作為出度 edge[tot].to = a; edge[tot].next = head[b]; head[b] = tot++; into[a]++;//記錄入度 } topu(); if (ans != n)//有可能在中間出現矛盾,必須保證每個地方都不矛盾 sum = -1; cout << sum << endl; } }
2018-04-10
hdu 2647 Reward(拓撲排序+反圖)