1. 程式人生 > >hdu 2647 Reward(拓撲排序+反圖)

hdu 2647 Reward(拓撲排序+反圖)

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>  
using
namespace 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(拓撲排序+反圖)