建图还是很明显的。
接着分两种情况:
1.图中不存在环:那么只要收买那些入度为0的点。如果这些点有的不能收买。就不能控制所有间谍。
2.图中存在环,那么对于这些在环中的点,我们只要收买数额最少的间谍。
于是我们用tarjan缩点:这样把第二种情况就变成了第一种情况。
所以大体流程是:用tarjan缩点,然后统计新图中入度为0的点愿意收买的数额。缩点的时候可以顺便维护每一个强联通分量的数额的最小值以及编号最小的节点。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(‘ ‘) 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 2e4 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ‘ ‘; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - ‘0‘; ch = getchar();} 27 if(last == ‘-‘) ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar(‘-‘); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + ‘0‘); 35 } 36 37 int n, m, r, a[maxn]; 38 vector<int> v[maxn]; 39 40 bool in[maxn]; 41 int dfn[maxn], low[maxn], cnt = 0; 42 stack<int> st; 43 int ccol = 0, col[maxn], val[maxn], Min[maxn]; 44 void tarjan(int now) 45 { 46 dfn[now] = low[now] = ++cnt; 47 st.push(now); in[now] = 1; 48 for(int i = 0; i < (int)v[now].size(); ++i) 49 { 50 if(!dfn[v[now][i]]) 51 { 52 tarjan(v[now][i]); 53 low[now] = min(low[now], low[v[now][i]]); 54 } 55 else if(in[v[now][i]]) low[now] = min(low[now], dfn[v[now][i]]); 56 } 57 if(dfn[now] == low[now]) 58 { 59 int x; 60 ++ccol; 61 do 62 { 63 x = st.top(); st.pop(); 64 in[x] = 0; 65 col[x] = ccol; 66 val[ccol] = min(val[ccol], a[x]); 67 Min[ccol] = min(Min[ccol], x); 68 69 }while(x != now); 70 } 71 } 72 73 int du[maxn]; 74 void newGraph(int now) 75 { 76 int u = col[now]; 77 for(int i = 0; i < (int)v[now].size(); ++i) 78 { 79 int e = col[v[now][i]]; 80 if(u == e) continue; 81 du[e]++; 82 } 83 } 84 85 int main() 86 { 87 n = read(); m = read(); 88 for(int i = 1; i <= n; ++i) a[i] = val[i] = Min[i] = INF; 89 for(int i = 1; i <= m; ++i) 90 { 91 int x = read(), y = read(); 92 a[x] = y; 93 } 94 r = read(); 95 for(int i = 1; i <= r; ++i) 96 { 97 int x = read(), y = read(); 98 v[x].push_back(y); 99 } 100 for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i); 101 for(int i = 1; i <= n; ++i) newGraph(i); 102 int sum = 0, Mn = INF; 103 for(int i = 1; i <= ccol; ++i) if(!du[i]) 104 { 105 if(val[i] == INF) Mn = min(Mn, Min[i]); //如果这个点不能收买 106 else sum += val[i]; 107 } 108 if(Mn != INF) printf("NO\n%d\n", Mn); 109 else printf("YES\n%d\n", sum); 110 return 0; 111 } 112
原文地址:https://www.cnblogs.com/mrclr/p/9663563.html
时间: 2024-10-03 16:24:37