1. 程式人生 > >[luogu1262]間諜網絡

[luogu1262]間諜網絡

memset efi urn clu algorithm cstring continue tarjan 我們

傳送門

考慮tarjan縮點,形成一個DAG。若要控制所有間諜,則從所有可以被控制的點出發,可以遍歷整個圖,否則就是存在無法控制。為了控制所有人,我們需要把入度為0的點的權值相加作為答案。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 3005
#define MAXM 8005
#define INF 2147483647

int head[MAXN];
struct edge{
    int v,next;
}G[MAXM];
int u[MAXM],v[MAXM];

struct Node{
    int cost,u;
}E[MAXN];

int color[MAXN],value[MAXN],size[MAXN],least[MAXN];
int vis[MAXN],st[MAXN],top = 0;
int dfn[MAXN],low[MAXN];

int N,P,R;
int tot = 0,color_num = 0,num = 0;

inline void add(int u,int v){
    G[++tot].v = v;G[tot].next = head[u];head[u] = tot;
}

void tarjan(int u){
    
    dfn[u] = low[u] = ++num;
    vis[u] = 1;st[++top] = u;
    for(register int i=head[u];i;i=G[i].next){
        int v = G[i].v;
        if(!dfn[v]){
            tarjan(v);
            if(low[v]<low[u])low[u] = low[v];
        }
        else if(vis[v]&&low[u]>dfn[v])low[u] = dfn[v];
    }

    if(low[u]==dfn[u]){
        ++color_num;color[u] = color_num;
        vis[u] = 0;
        least[color_num] = u;
        while(st[top]!=u){
            vis[st[top]] = 0;
            color[st[top]] = color_num;
            if(least[color_num]>st[top])least[color_num] = st[top];
            top--;
        }
        top--;
    }

}

void dfs(int u){
    dfn[u] = ++num;
    for(register int i=head[u];i;i=G[i].next){
        if(!dfn[G[i].v])dfs(G[i].v);
    }
}

int main(){

    std::memset(vis,0,sizeof(vis));
    std::memset(head,0,sizeof(head));
    std::memset(G,0,sizeof(G));
    std::memset(dfn,0,sizeof(dfn));

    scanf("%d",&N);
    scanf("%d",&P);
    for(register int i=1;i<=P;++i){
        scanf("%d%d",&E[i].u,&E[i].cost);
    }

    scanf("%d",&R);
    for(register int i=1;i<=R;++i){
        scanf("%d%d",&u[i],&v[i]);
        add(u[i],v[i]);
    }

    for(register int i=1;i<=N;++i){
        if(!dfn[i])tarjan(i);
    }

    std::memset(dfn,0,sizeof(dfn));
    std::memset(head,0,sizeof(head));
    std::memset(G,0,sizeof(G));
    std::memset(size,0,sizeof(size));

    for(register int i=1;i<=R;++i){
        if(color[u[i]]==color[v[i]])continue;
        add(color[u[i]],color[v[i]]);
        size[color[v[i]]]++;
    }

    for(register int i=1;i<=color_num;++i){
        value[i] = INF;
    }

    for(register int i=1;i<=P;++i){
        value[color[E[i].u]] = std::min(value[color[E[i].u]],E[i].cost);
    }

    num = 0;
    for(register int i=1;i<=color_num;++i){
        if(value[i]!=INF&&!dfn[i]){
            dfs(i);
        }
    }

    int ans = INF;
    for(register int i=1;i<=color_num;++i){
        if(!dfn[i])ans = std::min(ans,least[i]);
    }

    if(ans!=INF){
        puts("NO");
        printf("%d",ans);
        return 0;
    }

    ans = 0;
    for(register int i=1;i<=color_num;++i){
        if(!size[i])ans += value[i];
    }
    puts("YES");
    printf("%d",ans);
    return 0;
}

[luogu1262]間諜網絡