洛谷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 }

 

 
posted @ 2022-09-06 19:30  Keyzee  阅读(27)  评论(0编辑  收藏  举报