洛谷P1262 间谍网络(tarjan求强连通分量+缩点)
题目链接:https://www.luogu.com.cn/problem/P1262
思路:首先,我们能够知道,入读为0 的点 如果不能被收买的话,那么此题是无解的。其次,如果图中存在环的话,那么环中每个点的最小值 就是这个环所成的点的值,环中每个点是相互可以到达的,而且如果环处在中间的话,我们是可以无视掉的,我们只考虑环在开头的情况,也就是缩点之后,入读为0的点。通过tarjan求出强连通分量后进行缩点,然后计算入读为0的点所花费的金额就ok了。
代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<map>
5 #include<queue>
6 #include<set>
7 #include<algorithm>
8 #include<stack>
9 #include<cmath>
10 #include<cstring>
11 #include<string>
12 using namespace std;
13 #define gc getchar()
14 #define rd(x) read(x)
15 #define el '\n'
16 #define rep(i, a, n) for(int i = (a); i <= n; ++i)
17 #define per(i, a, n) for(int i = (a); i >= n; --i)
18 using ll = long long;
19 using db = double;
20 using ldb = long double;
21 const int mod = 1e9 + 7;
22 const int inf = 0x3f3f3f3f;
23 const int N = 100000 + 10;
24
25 template <typename _T>
26 inline void read(_T& f) {
27 f = 0; _T fu = 1; char c = gc;
28 while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = gc; }
29 while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = gc; }
30 f *= fu;
31 }
32
33 template <typename T>
34 void print(T x) {
35 if (x < 0) putchar('-'), x = -x;
36 if (x < 10) putchar(x + 48);
37 else print(x / 10), putchar(x % 10 + 48);
38 }
39
40 template <typename T>
41 void print(T x, char t) {
42 print(x); putchar(t);
43 }
44
45 int dfn[N], low[N], ins[N], scc[N], in[N];
46 int dfncnt, scccnt;
47 stack<int>st;
48 vector<int>G[N];
49 vector<int>DAG[N];
50 int vi[N];
51 int coin[N];
52 int vp[N];
53
54 int n, m, p;
55 int pmax;
56
57 void tarjan(int u) {
58 dfn[u] = ++dfncnt;
59 low[u] = dfncnt;
60 st.push(u);
61 ins[u] = true;
62 for (int i = 0; i < G[u].size(); i++) {
63 int v = G[u][i];
64 if (!dfn[v]) {
65 tarjan(v);
66 low[u] = min(low[u], low[v]);
67 }
68 else if (ins[v]) {
69 low[u] = min(low[u], dfn[v]);
70 }
71 }
72 if (dfn[u] == low[u]) {
73 int v;
74 ++scccnt;
75 pmax = max(pmax, scccnt);
76 do {
77 A v = st.top();
78 st.pop();
79 ins[v] = false;
80 scc[v] = scccnt;
81 coin[scccnt] = min(coin[scccnt], vi[v]);
82 vp[scccnt] = min(vp[scccnt], v);
83
84 } while (u != v);
85 }
86 }
87
88 void getdag() {
89 for (int i = 1; i <= n; i++) {
90 if (!dfn[i]) {
91 tarjan(i);
92 }
93 }
94 for (int u = 1; u <= n; u++) {
95 for (int j = 0; j < G[u].size(); j++) {
96 int v = G[u][j];
97 if (scc[u] != scc[v]) {
98 DAG[scc[u]].push_back(scc[v]);
99 in[scc[v]]++;
100 }
101 }
102 }
103 }
104
105 int main() {
106
107 ios::sync_with_stdio(false);
108 cin.tie(0), cout.tie(0);
109 //int n, m;
110 cin >> n;
111 cin >> p;
112 memset(vp, 0x3f, sizeof(vp));
113 memset(coin, 0x3f, sizeof(coin));
114 memset(vi, 0x3f, sizeof(vi));
115 for (int i = 1; i <= p; i++) {
116 int a, b;
117 cin >> a >> b;
118 vi[a] = b;
119 }
120 cin >> m;
121 for (int i = 1; i <= m; i++) {
122 int u, v;
123 cin >> u >> v;
124 G[u].push_back(v);
125 }
126 getdag();
127 int ans = 0;
128 for (int i = 1; i <= pmax; i++) {
129 if (!in[i]) {
130 if (coin[i] == inf) {
131 cout << "NO" << el;
132 cout << vp[i] << el;
133 return 0;
134 }
135 ans += coin[i];
136 }
137 }
138 cout << "YES" << el;
139 cout << ans << el;
140
141 return 0;
142 }
永远热爱,永远向着光。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下