luogu1262 间谍网络

贿赂所有能贿赂的,如果还有人不被访问则显然是NO。
否则,必定为YES。强联通分量缩成一个DAG,若某点的入度为零,则答案要算上它的。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct Edge{
    int fro, too, nxt;
}edge[8005];
int n, p, uu, vv, scc, w[3005], cnt, hea[3005], dfn[3005], loo[3005], ind, sta[3005], din, r, ans;
int minn[3005], bel[3005], dge[3005];
bool ins[3005];
void add_edge(int fro, int too){
    edge[++cnt].nxt = hea[fro];
    edge[cnt].fro = fro;
    edge[cnt].too = too;
    hea[fro] = cnt;
}
void dfs(int u){
    ins[u] = true;
    for(int i=hea[u]; i; i=edge[i].nxt){
        int t=edge[i].too;
        if(!ins[t]) dfs(t);
    }
}
void tarjan(int u){
    sta[++din] = u;
    ins[u] = true;
    dfn[u] = loo[u] = ++ind;
    for(int i=hea[u]; i; i=edge[i].nxt){
        int t=edge[i].too;
        if(!dfn[t]){
            tarjan(t);
            loo[u] = min(loo[u], loo[t]);
        }
        else if(ins[t]) loo[u] = min(loo[u], dfn[t]);
    }
    int j;
    if(dfn[u]==loo[u]){
        scc++;
        do{
            j = sta[din--];
            bel[j] = scc;
            ins[j] = false;
            minn[scc] = min(minn[scc], w[j]);
        }while(dfn[j]!=dfn[u]);
    }
}
int main(){
    cin>>n>>p;
    memset(w, 0x3f, sizeof(w));
    memset(minn, 0x3f, sizeof(minn));
    for(int i=1; i<=p; i++) scanf("%d", &uu), scanf("%d", &w[uu]);
    cin>>r;
    for(int i=1; i<=r; i++){
        scanf("%d %d", &uu, &vv);
        add_edge(uu, vv);
    }
    for(int i=1; i<=n; i++)
        if(w[i]!=0x3f3f3f3f && !ins[i])
            dfs(i);
    for(int i=1; i<=n; i++)
        if(!ins[i]){
            cout<<"NO\n"<<i;
            return 0;
        }
    memset(ins, 0, sizeof(ins));
    for(int i=1; i<=n; i++)
        if(!dfn[i])
            tarjan(i);  
    for(int i=1; i<=cnt; i++)
        if(bel[edge[i].fro]!=bel[edge[i].too])
            dge[bel[edge[i].too]]++;
    for(int i=1; i<=scc; i++){
        if(!dge[i])
            ans += minn[i];
    }
    cout<<"YES\n"<<ans;
    return 0;
}

转载于:https://www.cnblogs.com/poorpool/p/7943382.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值