zoukankan      html  css  js  c++  java
  • 间谍网络(Tarjan缩点)

    由于外国间谍的大量渗入,国家安全正处于高度危机之中。如果 A间谍手中掌握着关于 B 间谍的犯罪证据,则称 A 可以揭发 B。有些间谍接受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报。所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子。因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报。
    我们的反间谍机关提供了一份资料,包括所有已知的受贿的间谍,以及他们愿意收受的具体数额。同时我们还知道哪些间谍手中具体掌握了哪些间谍的资料。假设总共有 n 个间谍,每个间谍分别用 1 到 3000 的整数来标识。
    请根据这份资料,判断我们是否可能控制全部的间谍,如果可以,求出我们所需要支付的最少资金。否则,输出不能被控制的一个间谍。


    首先我们可以看出来的是要区分联通块,所以由此想到了tarjan,然后我们来看对于一个连通分量,我们只需要在里面有一个点就可以

    所以想到Tarjan缩点,每个店的点权就是原先联通分量里的最小的点权

    然后我们发现只求出联通分量是不够的

    因为可能联通分量之间还有边,而只要有一条入边,就不用再选了

    所以需要花费的只有入读为0的边

    下面给出代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    inline int rd(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int n,m,k;
    int head[100006],nxt[100006],to[100006];
    int total=0;
    void add(int x,int y){
        total++;
        to[total]=y;
        nxt[total]=head[x];
        head[x]=total;
        return ;
    }
    int v[100006];
    int dfn[100006];
    int low[100006];
    int tot=0;
    int color[100006];
    int book[100006];
    int sta[100006],set=0;
    int dis[100006];
    int cnt=0;
    void tarjan(int x){
        low[x]=dfn[x]=++tot;
        book[x]=1;
        sta[++set]=x;
        for(int e=head[x];e;e=nxt[e]){
            if(!dfn[to[e]]){
                tarjan(to[e]);
                low[x]=min(low[x],low[to[e]]);
            }
            else if(book[to[e]]) low[x]=min(low[x],dfn[to[e]]);
        }
        if(dfn[x]==low[x]){
            dis[++cnt]=min(dis[cnt],v[x]);
            color[x]=cnt;
            book[x]=0;
            while(set&&sta[set]!=x){
                dis[cnt]=min(dis[cnt],v[sta[set]]);
                color[sta[set]]=cnt;
                book[sta[set]]=0;
                set--;
            }
            set--;
        }
        return ;
    }
    int du[100006];
    int main(){
        memset(dis,127,sizeof(dis));
        memset(v,127,sizeof(v));
        n=rd(),k=rd();
        for(int i=1;i<=k;i++){
            int x=rd();
            v[x]=rd();
        }
        m=rd();
        for(int i=1;i<=m;i++){
            int x=rd(),y=rd();
            add(x,y);
        }
        for(int i=1;i<=n;i++) if(!dfn[i]&&v[i]!=2139062143) tarjan(i);
        for(int i=1;i<=n;i++) if(!dfn[i]){
            printf("NO
    ");
            write(i);
            return 0;
        }
        printf("YES
    ");
        for(int i=1;i<=n;i++) for(int e=head[i];e;e=nxt[e]) if(color[i]!=color[to[e]]) du[color[to[e]]]++;
        int ans=0;
        for(int i=1;i<=cnt;i++) if(!du[i]) ans+=dis[i];
        write(ans);
        return 0;
    }
  • 相关阅读:
    Oracle 创建dblink
    好的博客
    Java项目导出war包 security alert:integrity check error”
    tomcat7.0 处理问题
    项目支持Servlet3.0的新特性
    oracle replace函数
    JavaWeb项目连接Oracle数据库
    LeetCode OJ
    LeetCode OJ
    LeetCode OJ
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9852640.html
Copyright © 2011-2022 走看看