https://www.luogu.com.cn/problem/P1262
第5題 抓間諜 檢視測評資料資訊
由於外國間諜的大量滲入,國家安全正處於高度的危機之中。如果 A 間諜手中掌握著關於 B 間諜的犯罪證據,則稱 A 可以揭發 B。有些間
諜收受賄賂,只要給他們一定數量的美元,他們就願意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜
網中的每一分子。因為一旦我們逮捕了一個間諜,他手中掌握的情報都將歸我們所有,這樣就有可能逮捕新的間諜,掌握新的情報。
我們的反間諜機關提供了一份資料,包括所有已知的受賄的間諜,以及他們願意收受的具體數額。同時我們還知道哪些間諜手中具體掌
握了哪些間諜的資料。假設總共有 n 個間諜(n 不超過 3000),每個間諜分別用 1 到 3000 的整數來標識。
請根據這份資料,判斷我們是否有可能控制全部的間諜,如果可以,求出我們所需要支付的最少資金。否則,輸出不能被控制的一個間諜。
輸入格式
第一行只有一個整數 n。
第二行是整數 p。表示願意被收買的人數,1<=p<= n。
接下來的 p 行,每行有兩個整數,第一個數是一個願意被收買的間諜的編號,第二個數表示他將會被收買的數額。這個數額不超過 20000。
緊跟著一行只有一個整數 r,1<= r<=8000。然後 r 行,每行兩個正整數,表示數對 (A, B),A 間諜掌握 B 間諜的證據。
輸出格式
如果可以控制所有間諜,第一行輸出 `YES`,並在第二行輸出所需要支付的賄金最小值。否則輸出 `NO`,並在第二行輸出不能控制的間諜中,編號最小的間諜編號。
輸入/輸出例子1
輸入:
3
2
1 10
2 100
2
1 3
2 3
輸出:
YES
110
樣例解釋
無
縮點
1.有環:環中間諜賄賂最小值
2.入度為0:必須賄賂
無法賄賂:“NO”
#include <bits/stdc++.h> using namespace std; const int N=160005, MAX=1e9+5; int n, m, p, u1, v1, x, money, t[N]; int dfn[N], low[N], idx=0, cnt=0, id[N], rd[N], Minid[N], Minmo[N], Aans=0, Bans; stack<int> st; vector<int> a[N]; void dfs(int u) { dfn[u]=low[u]=++idx; st.push(u); for (int i=0; i<a[u].size(); i++) { int v=a[u][i]; if (!dfn[v]) { dfs(v); low[u]=min(low[u], low[v]); } else if (!id[v]) low[u]=min(low[u], dfn[v]); } if (dfn[u]==low[u]) { cnt++; while (st.top()!=u) { id[st.top()]=cnt; Minmo[cnt]=min(Minmo[cnt], t[st.top()]); Minid[cnt]=min(Minid[cnt], st.top()); st.pop(); } id[st.top()]=cnt; Minmo[cnt]=min(Minmo[cnt], t[st.top()]); Minid[cnt]=min(Minid[cnt], st.top()); st.pop(); } } int main() { for (int i=0; i<N-5; i++) t[i]=Minid[i]=Minmo[i]=MAX; scanf("%d%d", &n, &p); for (int i=1; i<=p; i++) { scanf("%d%d", &x, &money); t[x]=money; } scanf("%d", &m); for (int i=1; i<=m; i++) { scanf("%d%d", &u1, &v1); a[u1].push_back(v1); } for (int i=1; i<=n; i++) if (!dfn[i] && t[i]!=MAX) dfs(i); for (int i=1; i<=n; i++) if (!dfn[i]) { printf("NO\n%d", i); return 0; } for (int u=1; u<=n; u++) for (int j=0; j<a[u].size(); j++) { int v=a[u][j]; if (id[u]!=id[v]) rd[id[v]]++; } for (int i=1; i<=cnt; i++) { if (rd[i]!=0) continue; Bans+=Minmo[i]; } printf("YES\n%d", Bans); return 0; }