zoukankan      html  css  js  c++  java
  • 洛谷 1262 间谍网络——缩点+拓扑

    题目:https://www.luogu.org/problemnew/show/P1262

    当然是缩点。一个点的收买价就是旗下点的最小值。然后从入度为0的点挨个dfs。

    但其实不对。可能入度为0的那个开头是不能收买的,但后面一个有入度的点可以收买。

    所以应该像拓扑排序那样遍历每个点。注意打过vis标记就不再算了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=3005,M=8005,INF=0x3f3f3f3f;
    int n,p,m,a[N],hd[N],xnt,to[M],nxt[M],fr[M];
    int dfn[N],low[N],tim,col[N],cnt,rd[N],c[N];
    int ans,sta[N],top,q[N],he,tl;
    bool ins[N];
    struct Ed{
        int nxt,to;Ed(int n=0,int t=0):nxt(n),to(t) {}
    }ed[M];
    int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    void add(int x,int y)
    {
        to[++xnt]=y; nxt[xnt]=hd[x]; hd[x]=xnt; fr[xnt]=x;
    }
    void ade(int x,int y)
    {
        ed[++xnt]=Ed(hd[x],y); hd[x]=xnt; rd[y]++;
    }
    void tarjan(int cr)
    {
        dfn[cr]=low[cr]=++tim;
        sta[++top]=cr; ins[cr]=1;
        for(int i=hd[cr],v;i;i=nxt[i])
        {
            if(!dfn[v=to[i]])
                tarjan(v),low[cr]=min(low[cr],low[v]);
            else if(ins[v])
                low[cr]=min(low[cr],dfn[v]);
        }
        if(dfn[cr]==low[cr])
        {
            cnt++; c[cnt]=INF;
            while(sta[top]!=cr)
            {
                int k=sta[top--];
                col[k]=cnt; ins[k]=0;
                c[cnt]=min(c[cnt],a[k]);
            }
            top--; col[cr]=cnt; ins[cr]=0;
            c[cnt]=min(c[cnt],a[cr]);
        }
    }
    void dfs(int cr)
    {
        ins[cr]=1;
        for(int i=hd[cr];i;i=ed[i].nxt)
            dfs(ed[i].to);
    }
    int main()
    {
        n=rdn(); p=rdn();
        memset(a,0x3f,sizeof a);
        for(int i=1,u;i<=p;i++)
        {
            u=rdn();a[u]=rdn();
        }
        m=rdn();
        for(int i=1,u,v;i<=m;i++)
        {
            u=rdn(); v=rdn(); add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        xnt=0;
        memset(hd,0,sizeof hd);
        for(int i=1;i<=m;i++)
            if(col[to[i]]!=col[fr[i]])
                ade(col[fr[i]],col[to[i]]);
        memset(ins,0,sizeof ins);
        for(int i=1;i<=cnt;i++)
            if(!rd[i])
                q[++tl]=i;
        while(he<tl)
        {
            int k=q[++he];
            if(c[k]<INF&&!ins[k]) ans+=c[k],dfs(k);
            for(int i=hd[k],v;i;i=ed[i].nxt)
            {
                rd[v=ed[i].to]--;
                if(!rd[v]) q[++tl]=v;
            }
        }
        for(int i=1;i<=n;i++)
            if(!ins[col[i]])
            {
                printf("NO
    %d
    ",i);
                return 0;
            }
        printf("YES
    %d
    ",ans);
        return 0;
    }
  • 相关阅读:
    MoodNotes产品分析及功能说明书
    C#探秘系列(十)WPF:打开文件选择器选择文件并保存
    C#探秘系列(九)WPF连接Mysql数据库
    C#探秘系列(八)WPF数据绑定
    C#探秘系列(七):XML文件操作(一)
    #安卓杂记(七):自定义控件及属性获取
    C#探秘系列(六)
    安卓问题报告小记(七)
    121. Best Time to Buy and Sell Stock
    566. Reshape the Matrix
  • 原文地址:https://www.cnblogs.com/Narh/p/9702848.html
Copyright © 2011-2022 走看看