P1262 间谍网络(Tarjan缩图+dfs遍历)
买通间谍,有意思哦.有向图,考虑拓扑,要全部人的信息吧啦吧啦...
先缩图,缩图的时候注意一个连通分量里面如果有两个人被贿赂,题目要求用钱最少,所以就取最少的那个人的金额为该连通分量的贿赂金
还要保存连通分量中的最小编号.
看入读为0的点是不是都被贿赂了,入读0点需要钱的总和就是第一种情况的结果,
如果不是,就把被贿赂的所有点dfs下去,被dfs的点标记为信息可以得到
然后循环,取信息不能的到的连通分量重点的最小值就是第二种情况的结果.
#include<iostream> #include<string> #include<stack> #include<stdio.h> #include<queue> #include<string.h> #include<map> #include<unordered_map> #include<vector> #include<iomanip> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; #define INF 0x7fffffff const int maxn = 1e5 + 100; const int maxm = 1e6 + 100; int read() { char p = getchar(); while (p < '0' || '9' < p)p = getchar(); int sum = 0; while ('0' <= p && p <= '9') sum = sum * 10 + p - '0', p = getchar(); return sum; } struct E { int from,to, nxt; }e[maxm],e2[maxm]; int tot, hd[maxn],hd2[maxn],tot2; void add(int f, int to) { e[++tot].nxt = hd[f]; e[tot].to = to; e[tot].from = f; hd[f] = tot; } void add2(int f, int to) { e2[++tot2].nxt = hd2[f]; e2[tot2].to = to; e2[tot2].from = f; hd2[f] = tot2; } int low[maxn], fcn[maxn], cnt, stk[maxn], instk[maxn], pp; int colnum, col[maxn]; int showhui[maxn],colshowhui[maxn],colmi[maxn]; void Tarjan(int u) { low[u] = fcn[u] = ++tot; stk[++pp] = u; instk[u] = 1; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].to; if (!fcn[v]) { Tarjan(v); low[u] = min(low[u], low[v]); } else if (instk[v]) { low[u] = min(low[u], fcn[v]); } } if (low[u] == fcn[u]) { colnum++; int mi = INF; int minum = INF; bool flg = 0; //cout << colnum << ":"; while (1) { int t = stk[pp--]; //cout << " " << t; instk[t] = 0; col[t] = colnum; if (showhui[t]) { flg = 1; mi = min(mi, showhui[t]); } minum = min(minum, t); if (t == u)break; } //cout << endl; if(flg)colshowhui[colnum] = mi; else colshowhui[colnum] = 0; colmi[colnum] = minum; //cout <<mi << " " << minum << endl; } } bool beget[maxn]; void dfs(int u) { beget[u] = 1; for (int i = hd2[u]; i; i = e2[i].nxt) { int v = e2[i].to; if (!beget[v]) { //cout << v << endl; dfs(v); } } } int res,ans; int du[maxn]; bool flg; void work() { flg = 1; res = 0; ans = INF; for (int i = 1; i <= colnum; i++) { if (du[i] == 0){ if (colshowhui[i]) { res += colshowhui[i]; } else { flg = 0; } } } if (flg)return; queue<int>Q; for (int i = 1; i <= colnum; i++) { if (colshowhui[i]) { Q.push(i); } } while (!Q.empty()) { int t = Q.front(); Q.pop(); //cout << t << endl; dfs(t); } for (int i = 1; i <= colnum; i++) { if (!beget[i]) { //cout << i << endl; ans=min(ans,colmi[i]); } } } int n, p, m; int main() { //freopen("test.txt", "r", stdin); n = read(), p = read(); for (int i = 1; i <= p; i++) { int u = read(); showhui[u] = read(); } m = read(); for (int i = 1; i <= m; i++) { int u = read(), v = read(); add(u, v); } for (int i = 1; i <= n; i++) { if (!fcn[i])Tarjan(i); } for (int i = 1; i <= m; i++) { int u = e[i].from, v = e[i].to; if (col[u] != col[v]) { //cout << col[u] << col[v] << endl; add2(col[u], col[v]); du[col[v]]++; } } work(); if (flg) { printf("YES\n%d",res); } else { printf("NO\n%d", ans); } return 0; }