Codeforces Round #791(Div 2)——D

D

Problem - D - Codeforces

题意:

  给定一个有向图,每个点有自己的点权,求一条长度为K的路径使得路径上的最大点权最小,输出该条路径上的最大点权。

思路:(二分+拓扑排序)

  最小值最大的题考虑二分解决。

  我们每次二分答案为mx,以此判断有没有某条路径的最大值为mx且长度为k。因为我们要保证二分出来的mx是该条路径上最大的点权,所以所有大于mx的点我们都要舍弃。

  其次如果路径中含环那必然是可以的,如果不含吗,就需要判断是否存在长度为k,最大值为mx的路径

  举个例子:

    最初的图       

  当k == 4时,当我们判断mid = 4(既mx=4)时,则存在这样一条路径

                 

 

    chick返回true

  判断环的时候可以通过拓扑排序来判断

  在chick的时候需要注意的是,因为我们每次取的是小于等于mx的点,所以每次每个点的入度都不同,都需要重新统计

 1 const int N = 2e5 + 10,INF = 0x3f3f3f3f3f;
 2 int n, m, k, w[N];
 3 vector<int> g[N];
 4 int vis[N], deg[N], deep[N];/*vis判断是否小于等于mx,deg统计入度,deep统计路径长度*/
 5 vector<pair<int, int> >e;
 6 
 7 bool chick(int mx) {
 8     for (int i = 1; i <= n; ++i) vis[i] = 0, deg[i] = 0, deep[i] = -INF;
 9     for (int i = 1; i <= n; ++i) {
10         if (w[i] <= mx)vis[i] = 1;
11     }
12     for (auto it : e) {
13         if (w[it.first] <= mx && w[it.second] <= mx) {
14             deg[it.second]++;
15         }
16     }
17     queue<int> q;
18     for (int i = 1; i <= n; ++i ) {
19         if (vis[i] && !deg[i])q.push(i),deep[i] = 1;
20     }
21     while (q.size()) {
22         int u = q.front();
23         q.pop();
24         for (int s : g[u]) {
25             if (!vis[s]) continue;
26             deep[s] = max(deep[s], deep[u] + 1);
27             if (deep[s] >= k) return 1;
28             deg[s]--;
29             if (deg[s] == 0) q.push(s);
30         }
31     }
32     for (int i = 1; i <= n; ++i) {
33         if (vis[i] && deg[i] > 0)return 1;
34 
35     }
36     return 0;
37 }
38 
39 void solve() {
40     cin >> n >> m >> k;
41     for (int i = 1; i <= n; ++i) cin >> w[i];
42     for (int i = 1; i <= m; ++i) {
43         int x, y;
44         cin >> x >> y;
45         g[x].push_back(y);
46         e.push_back({x, y});
47     }
48     if (k == 1) {
49         cout << *max_element(w + 1, w + 1 + n) << endl;
50         return;
51     }
52     int ans = INF;
53     int l = 0, r = 1e9 + 1;
54     for (int i = 1; i <= 50; ++i) {
55         int mid = (l + r) >> 1;
56         if (chick(mid)) {
57             ans = min(ans, mid);
58             r = mid - 1;
59         } else l = mid + 1;
60     }
61     if (ans == INF) {
62         cout << -1 << endl;
63     } else cout << ans << endl;
64 }

 

posted @ 2022-05-15 13:34  empty_y  阅读(34)  评论(0)    收藏  举报