题目链接: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 }
标签:缩点,tarjan,洛谷,int,void,scccnt,low,include From: https://www.cnblogs.com/wabi/p/16663085.html