zoukankan      html  css  js  c++  java
  • Luogu P2002 消息扩散&&P1262 间谍网络

    怕自己太久没写Tarjan了就会把这种神仙算法忘掉。

    其实这种类型的图论题的套路还是比较简单且显然的。

    P2002 消息扩散

    很显然的题目,因为在一个环(其实就是强连通分量)中的城市都只需要让其中一个知道就可以让其它的城市都得知信息了。

    因此我们把在一个强连通分量中的点都缩点,然后就得到一个DAG

    然后我们只需要给入度为0的点传递信息即可

    CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=100005;
    struct edge
    {
        int to,next;
    }e[N*5];
    int head[N],col[N],ru[N],dfn[N],low[N],stack[N],n,m,x,y,cnt,tot,top,sum,ans;
    bool vis[N];
    inline char tc(void)
    {
        static char fl[100000],*A=fl,*B=fl;
        return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
        x=0; char ch=tc();
        while (ch<'0'||ch>'9') ch=tc();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline void add(int x,int y)
    {
        e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
    }
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    inline void Tarjan(int now)
    {
        dfn[now]=low[now]=++tot; stack[++top]=now; vis[now]=1;
        for (register int i=head[now];i^-1;i=e[i].next)
        if (!dfn[e[i].to])
        {
            Tarjan(e[i].to);
            low[now]=min(low[now],low[e[i].to]);
        } else if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
        if (!(low[now]^dfn[now]))
        {
            col[now]=++sum; vis[now]=0;
            while (stack[top]!=now)
            {
                col[stack[top]]=sum; vis[stack[top--]]=0;
            } --top;
        }
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        memset(head,-1,sizeof(head));
        memset(e,-1,sizeof(e));
        register int i,j; read(n); read(m);
        for (i=1;i<=m;++i)
        read(x),read(y),add(x,y);
        for (i=1;i<=n;++i)
        if (!dfn[i]) Tarjan(i);
        for (i=1;i<=n;++i)
        for (j=head[i];j^-1;j=e[j].next)
        if (col[i]^col[e[j].to]) ++ru[col[e[j].to]];
        for (i=1;i<=sum;++i)
        if (!ru[i]) ++ans;
        printf("%d",ans);
        return 0;
    }
    

    P1262 间谍网络

    这个的话读一下题目就可以发现这是前一题的加权版

    然后对于一个强连通分量中的点,在缩点后的权值应该是多少呢。

    很显然,肯定找最便宜的人贿赂吗!

    所以我们上一题的操作之上加权然后还是找入度为0的点。

    不过注意下如果一个点的入度为0但是这个间谍无法被贿赂那么就无法被控制

    CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=3005,M=8005;
    struct edge
    {
        int to,next;
    }e[M];
    int head[N],col[N],ru[N],dfn[N],low[N],stack[N],a[N],s[N],num[N],n,m,x,y,cnt,tot,top,sum,ans,INF,p;
    bool vis[N];
    inline char tc(void)
    {
        static char fl[100000],*A=fl,*B=fl;
        return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
        x=0; char ch=tc();
        while (ch<'0'||ch>'9') ch=tc();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline void add(int x,int y)
    {
        e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
    }
    inline int min(int a,int b)
    {
        return a<b?a:b;
    }
    inline void Tarjan(int now)
    {
        dfn[now]=low[now]=++tot; stack[++top]=now; vis[now]=1;
        for (register int i=head[now];i^-1;i=e[i].next)
        if (!dfn[e[i].to])
        {
            Tarjan(e[i].to);
            low[now]=min(low[now],low[e[i].to]);
        } else if (vis[e[i].to]) low[now]=min(low[now],dfn[e[i].to]);
        if (!(low[now]^dfn[now]))
        {
            col[now]=++sum; s[sum]=a[now]; num[sum]=now; vis[now]=0;
            while (stack[top]!=now)
            {
                col[stack[top]]=sum; vis[stack[top]]=0;
                s[sum]=min(s[sum],a[stack[top--]]);
            } --top;
        }
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        memset(head,-1,sizeof(head));
        memset(e,-1,sizeof(e));
        memset(a,127,sizeof(a)); INF=a[0];
        register int i,j; read(n); read(p);
        for (i=1;i<=p;++i)
        read(x),read(y),a[x]=y;
        for (read(m),i=1;i<=m;++i)
        read(x),read(y),add(x,y);
        for (i=1;i<=n;++i)
        if (!dfn[i]) Tarjan(i);
        for (i=1;i<=n;++i)
        for (j=head[i];j^-1;j=e[j].next)
        if (col[i]^col[e[j].to]) ++ru[col[e[j].to]];
        for (i=1;i<=sum;++i)
        if (!ru[i])
        {
            if (!(s[i]^INF)) { printf("NO
    %d",num[i]); return 0; }
            ans+=s[i];
        }
        printf("YES
    %d",ans);
        return 0;
    }
    
  • 相关阅读:
    USACO Section 1.3 : Mixing Milk
    USACO Section 1.3 : Prime Cryptarithm
    USACO Section 1.2 : Name That Number
    USACO Section 1.3 : Calf Flac
    USACO Section 1.2 : Palindromic Squares
    Global.asax详解
    sql语句字符串处理大全
    ASP.net:URL重写实现IHttpHandler接口
    asp.net中使用基于角色role的Forms验证
    时间Table.TransformColumns(Power Query 之 M 语言)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9150128.html
Copyright © 2011-2022 走看看