“Hdu4966” GGS-DDU - 最小树形图/朱刘算法

Posted petewell

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“Hdu4966” GGS-DDU - 最小树形图/朱刘算法相关的知识,希望对你有一定的参考价值。

原文引用https://www.dazhuanlan.com/2019/08/26/5d6302f8c23db/


题目链接:传送门

Description

有一个人,想学习N个科目,每个科目都有相应的层次 有M个课程,M个课程的要求是,你的第c个科目的层次要达到l1,才可以参加,参加完这个课程后,你需要缴费money,但你的第d个科目的层次会达到l2 问如何花最少的钱,使得每个科目的层次都达到最高

Solution

每个科目的每个层次都看成一个点,每个科目的层次0和一个根连边,费用为0;每个科目的高层次向下一个低层次连边,费用为0(因为你高层次的会了就表示低层次的也会了) 然后用朱刘算法跑一遍最小树形图即可

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129


using namespace std;

const int Maxn = 500 + 10, Maxm = 2500 + 10, inf = INT_MAX;

struct node

int x, y, w;
edge[Maxm];

int N, M, cnt, Ans, Index;
int Map[55][500 + 10];

inline void Init()

cnt = Ans = Index = 0;


inline void add_edge (int x, int y, int z)

edge[++cnt].x = x;
edge[cnt].y = y;
edge[cnt].w = z;


int In[Maxn], Pre[Maxn];
int id[Maxn], Vis[Maxn];

inline int Solve (int root)

while (1)

for (int i = 1; i <= N; ++i) In[i] = inf;
for (int i = 1; i <= cnt; ++i)

int x = edge[i].x, y = edge[i].y;
if (x != y && edge[i].w < In[y])

Pre[y] = x;
In[y] = edge[i].w;


for (int i = 1; i <= N; ++i)
if (i != root && In[i] == inf) return -1;

int sum = 0;
memset(id, -1, sizeof id);
memset(Vis, -1, sizeof Vis);
In[root] = 0;
for (int i = 1; i <= N; ++i)

Ans += In[i];
int now = i;
while (Vis[now] != i && now != root && id[now] == -1)

Vis[now] = i;
now = Pre[now];


if (now != root && id[now] == -1)

int tmp = Pre[now];
++sum;
while (tmp != now)

id[tmp] = sum;
tmp = Pre[tmp];

id[now] = sum;


if (!sum) return Ans;

for (int i = 1; i <= N; ++i)
if (id[i] == -1) id[i] = ++sum;
for (int i = 1; i <= cnt; ++i)

int x = edge[i].x, y = edge[i].y;
edge[i].x = id[x]; edge[i].y = id[y];
if (id[x] != id[y])
edge[i].w -= In[y];

N = sum;
root = id[root];



int main()

#ifdef hk_cnyali
freopen("A.in", "r", stdin);
freopen("A.out", "w", stdout);
#endif
while (1)

scanf("%d%d", &N, &M);
if (N == M && !N) break;
Init();
for (int i = 1; i <= N; ++i)

int x;
scanf("%d", &x);
for (int j = 0; j <= x; ++j)
Map[i][j] = ++Index;
Map[i][501] = x;

while (M--)

int a, b, c, d, e;
scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
add_edge(Map[a][b], Map[c][d], e);


for (int i = 1; i <= N; ++i)
for (int j = 1; j <= Map[i][501]; ++j)

add_edge(Map[i][j], Map[i][j - 1], 0);


for (int i = 1; i <= N; ++i)
add_edge(0, Map[i][0], 0);

N = Index;

printf("%dn", Solve(0));

return 0;

以上是关于“Hdu4966” GGS-DDU - 最小树形图/朱刘算法的主要内容,如果未能解决你的问题,请参考以下文章

HDU:GGS-DDU

贪心HDU2037:今年暑假不AC

HDU 2037 今年暑假不AC(贪心)

HDU2037今年暑假不AC(贪心)

hdu4799 树型DP

hdu-2846 Repository