P1262 间谍网络(Tarjan缩图+dfs遍历)

P1262 间谍网络

买通间谍,有意思哦.有向图,考虑拓扑,要全部人的信息吧啦吧啦...

先缩图,缩图的时候注意一个连通分量里面如果有两个人被贿赂,题目要求用钱最少,所以就取最少的那个人的金额为该连通分量的贿赂金

还要保存连通分量中的最小编号.

看入读为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;
}

 

posted @ 2021-02-02 17:05  cono奇犽哒  阅读(71)  评论(0)    收藏  举报