zoukankan      html  css  js  c++  java
  • P1262 间谍网络

    P1262 间谍网络

    Tarjan缩点

    我们用Tarjan缩完点后,剩下若干个DAG图

    我们发现,只要每个图的所对应的强连通分量上有某人能被收买,显然整个DAG上的人都能被收买。

    于是我们就在Tarjan的过程中顺便维护每个强连通分量的对应最小费用,也就是分量中价格最便宜的那个人。

    (终于找到我会写的题了qwq)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    using namespace std;
    template <typename T> inline T min(T &a,T &b) {return a<b ? a:b;}
    template <typename T> inline void read(T &x){
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    }
    int n,m1,m2,ans,dfs_clock,dfn[3002],low[3002],tot,be[3002],_top,st[3002];
    int val1[3002],cnt,hd[3002],nxt[8002],ed[3002],poi[8002];
    int val2[3002],cnt2,hd2[3002],nxt2[8002],ed2[3002],poi2[8002];
    int in[3002]; bool flag[3002];
    inline void add(int x,int y){
        nxt[ed[x]]=++cnt; hd[x]= hd[x] ? hd[x]:cnt;
        ed[x]=cnt; poi[cnt]=y;
    }
    inline void add2(int x,int y){
        nxt2[ed2[x]]=++cnt2; hd2[x]= hd2[x] ? hd2[x]:cnt2;
        ed2[x]=cnt2; poi2[cnt2]=y;
    }
    inline void tarjan(int x){
        dfn[x]=low[x]=++dfs_clock; st[++_top]=x;
        for(int i=hd[x];i;i=nxt[i]){
            if(!dfn[poi[i]]) tarjan(poi[i]),low[x]=min(low[x],low[poi[i]]);
            else if(!be[poi[i]]) low[x]=min(low[x],dfn[poi[i]]);
        }
        if(dfn[x]==low[x]){
            be[x]=++tot; val2[tot]=val1[x];
            while(st[_top]!=x) be[st[_top]]=tot,val2[tot]=min(val2[tot],val1[st[_top--]]); //维护强连通分量的最小费用
            --_top;
        }
    }
    inline void dfs(int x){
        flag[x]=1;
        for(int i=hd2[x];i;i=nxt2[i]) if(!flag[poi2[i]]) dfs(poi2[i]);
    }
    int main(){
        memset(val1,127,sizeof(val1));
        memset(val2,127,sizeof(val2));
        read(n); read(m1); int q1,q2;
        for(int i=1;i<=m1;++i) read(q1),read(q2),val1[q1]=q2;
        read(m2);
        for(int i=1;i<=m2;++i) read(q1),read(q2),add(q1,q2);
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;++i) //建新图
            for(int j=hd[i];j;j=nxt[j])
                if(be[i]!=be[poi[j]])
                    add2(be[i],be[poi[j]]),++in[be[poi[j]]];
        bool ok=1;
        for(int i=1;i<=tot;++i)
            if(!in[i]){ //树根
                if(val2[i]==val2[0]) ok=0; //没有间谍可收买
                ans+=val2[i];
            }
        if(ok) printf("YES
    %d",ans);
        else{
            for(int i=1;i<=tot;++i) if(!in[i]&&val2[i]==val2[0]) dfs(i); //dfs找出所有解决不了的块
            for(int i=1;i<=n;++i) if(flag[be[i]]&&val1[i]==val1[0]) {printf("NO
    %d",i); break;} //注意单个间谍也不可以被收买 
        }return 0;
    }
  • 相关阅读:
    1767:字符合并
    成绩单
    floj 2264
    floj 2265 【lxs Contest #141】航海舰队
    CF932D Tree
    1745:分组
    1744:跳台阶
    Xamarin.Forms之跨平台性能
    Xamarin.Forms之部署和测试(性能)
    Xamarin.Forms数据绑定
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9691239.html
Copyright © 2011-2022 走看看