HDU 2647 逆向拓扑排序

令每一个员工都有一个自己的等级level[i] , 员工等级越高,那么工资越高,为了使发的钱尽可能少,所以每一级只增加一单位的钱

输入a b表示a等级高于b,那么我们反向添加边,令b—>a那么in[a]++,再进行拓扑排序,每次都让边的终点的level值大于起始点,那么要用max取较大值

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5
 6 using namespace std;
 7
 8 const int N = 10005;
 9 int n , m , level[N] ;
10 int first[N] , in[N] , k;
11
12 struct Path{
13     int y , next;
14 }path[N<<2];
15
16 void add_edge(int x, int y)
17 {
18     in[y]++;
19     path[k].y=y , path[k].next = first[x];
20     first[x] = k++;
21 }
22
23 bool DAG()
24 {
25     memset(level,0,sizeof(level));
26     int cnt = 0;//统计能形成无环图的最多的点的个数
27     queue<int> q;
28     for(int i = 1; i<= n ; i++)
29         if(in[i] == 0){
30             q.push(i);
31             level[i] = 0;
32         }
33     while(true){
34         if(q.empty()) break;
35         int u = q.front();
36         q.pop();
37         cnt++;
38         for(int i = first[u] ; i!=-1 ; i=path[i].next){
39             int v= path[i].y;
40             in[v]--;
41             level[v] = max(level[v] , level[u]+1);
42             if(in[v] == 0)
43                 q.push(v);
44         }
45     }
46     if(cnt<n) return false;
47     return true;
48 }
49
50 int main()
51 {
52    // freopen("a.in","rb",stdin);
53     int a,b;
54     memset(level , 0x3f , sizeof(level));
55     while(~scanf("%d%d",&n,&m)){
56         memset(first , -1 , sizeof(first));
57         memset(in , 0 , sizeof(in));
58         k=0;
59
60         for(int i=0 ; i<m ; i++){
61             scanf("%d%d",&a,&b);
62             add_edge(b , a);
63         }
64
65         if(DAG()){
66             int ans = 0;
67             for(int i = 1 ; i<=n ; i++)
68                 ans+=888+level[i];
69             printf("%d\n",ans);
70         }
71         else puts("-1");
72     }
73     return 0;
74 }
时间: 2025-01-10 13:44:34

HDU 2647 逆向拓扑排序的相关文章

hdu 2647 Reward (拓扑排序分层)

Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3815    Accepted Submission(s): 1162 Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wa

ACM: hdu 2647 Reward -拓扑排序

hdu 2647 Reward Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble

HDU 2647 Reward(拓扑排序)

Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how to distribute the rewards. The workers will compare their rewards ,and some

hdu 2647 Reward 拓扑排序。

Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4599    Accepted Submission(s): 1400 Problem Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he w

HDU 2647 Reward 拓扑排序

Reward Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Dandelion's uncle is a boss of a factory. As the spring festival is coming , he wants to distribute rewards to his workers. Now he has a trouble about how

hdu 2647 Reward(拓扑排序+反图)

题目链接:https://vjudge.net/contest/218427#problem/C 题目大意: 老板要给很多员工发奖金, 但是部分员工有个虚伪心态, 认为自己的奖金必须比某些人高才心理平衡: 但是老板很人道, 想满足所有人的要求, 并且很吝啬,想画的钱最少 输入若干个关系 a b a c c b 意味着a 的工资必须比b的工资高 同时a 的工资比c高: c的工资比b高 当出现环的时候输出-1 #include<iostream> #include<cstring> #

hdu 4857 逃生 拓扑排序+优先队列,逆向处理

hdu4857 逃生 题目是求拓扑排序,但不是按照字典序最小输出,而是要使较小的数排在最前面. 一开始的错误思路:给每个点确定一个优先级(该点所能到达的最小的点),然后用拓扑排序+优先对列正向处理,正向输出.这是错误的,如下样例: 1 5 4 5 2 4 3 2 1 3 1 正确的解法:是反向建边,点大的优先级高,用拓扑排序+优先队列,逆向输出序列即可. 根据每对限制,可确定拓扑序列,但此时的拓扑序列可能有多个(没有之间关系的点的顺序不定).本题要求较小的点排到前面,则可确定序列. (1)如果点

hdu--1285 &amp;&amp; 4857 --正向 || 逆向拓扑排序 &amp;&amp; 优先队列

头太晕了 喝了太多 .. 就想提一点 对于 拓扑排序的这2题 为什么一个是正向 一个是逆向 主要是看题目要求  因为拓扑排序的结果总是有很多种存在的 一般来说 它会让你输出它指定要求的形式的答案 那么 如果是按字典序输出 就是 greater<int> 情况下的优先队列 并且 正向 如果是尽量使小的数字 靠前输出 而不是追求 字典序 可以考虑 逆向拓扑 逆向输出 但 这些都不是唯一的 一定要分析好题目 曾经 看过一个讲动态规划的word  说拓扑是为DP作准备的 似乎有点道理 这两题 代码 实

HDU 4917 Permutation 拓扑排序的计数

题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以只一张有向无环图.这样子,我们就可以把排列计数的问题转化为一个图的拓扑排序计数问题. 拓扑排序的做法可以参见ZJU1346 . 因为题目中点的数量比较多,所以无法直接用状压DP. 但是题目中的边数较少,所以不是联通的,而一个连通块的点不超过21个,而且不同连通块之间可以看做相互独立的.所以我们可以对