zoukankan      html  css  js  c++  java
  • 强联通分量

    从9.13开始做强联通分量,开始强联通还把我给困住了,因为两个方程:
    1、low[u]=min{low[u],low[v]}

    2、low[u]=min{low[u],dfn[v]}

    多看网上的讲解和图就晓得了:

    其实第一个就是在每一次tarjan(u)之后,第二个就是在找到搜索过程中找到了根节点时;

    例题:间谍网络

    https://loj.ac/problem/10095

    算是一道有难度的题了吧,反正在打完模板之外还要进行一遍dfs。需要思考的有三:

    1、怎样判断能否控制完

    2、可以全部控制时,怎样选最小费用

    3、无法全部控制时,怎样选最小编号

    分析:缩点,成了一个有向无环图,dfs每个强联通子图,找入度为0的图,当这个子图中有能控制的人时,累加上。若遇到这个子图中没有能贿赂的人时,依然要dfs进行完,最后在for循环判断出最小编号即可(当然之前要对能控制的点标记~)

    对于问题2,其实已经解决了

    #include<bits/stdc++.h>
    using namespace std;
    int n,p,r;
    struct node{
        int to,next;
    }e[1100000];
    int num=0,head[11000];
    void add(int x,int y)
    {
        e[++num].to=y;
        e[num].next=head[x];
        head[x]=num;
    }
    int fee[100000];
    inline void read(int &x)
    {
        x=0;int f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
        x*=f;
    }
    int dfn[10000],low[10000],co[10000],col,sta[10000],si[10000],top=0;
    int jin[10000],lian[100000],bz[100000];
    void tarjan(int u)
    {
        low[u]=dfn[u]=++top;
        sta[top]=u;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else
            {
                if(!co[v]){
                    low[u]=min(low[u],dfn[v]);
                }
            }
        }
        if(low[u]==dfn[u])
        {
            co[u]=++col;
            si[col]++;
            if(bz[u])lian[col]=u;
            while(sta[top]!=u)
            {
                if(bz[sta[top]]&&fee[sta[top]]<fee[lian[col]])
                {
                    lian[col]=sta[top];
                }
                ++si[col];
                co[sta[top]]=col;
                top--;
            }
            top--;
        }
    }
    int vis[100000];
    void dfs(int u)
    {
        vis[u]=1;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!vis[v]){
                dfs(v);
            }
        }
    }
    int main()
    {
        for(int i=0;i<100000;i++) {
            lian[i]=4000;
            fee[i]=99999;
        }
        scanf("%d%d",&n,&p);
        for(int i=1;i<=p;i++)
        {    
            int per,f;
            scanf("%d%d",&per,&f);
            bz[per]=1;
            fee[per]=f;
        }
        scanf("%d",&r);
        for(int i=1;i<=r;i++)
        {    
            int x,y; 
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])tarjan(i);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=e[j].next)
            {
                int v=e[j].to;
                if(co[i]!=co[v])jin[co[v]]++;
            }
        }
    
        bool flag=1;
        int ans=0;
        for(int i=1;i<=col;i++)
        {
            if(!jin[i])
            {
                if(lian[i]!=4000)
                {
                    ans+=fee[lian[i]];
                    dfs(lian[i]);
                }
                else{
                    flag=0;
                }
            }
        }
        if(flag)
        {
            printf("YES
    %d",ans);
            return 0;
        }
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]){
                printf("NO
    %d",i);
                return 0;
            }
        }
    }
  • 相关阅读:
    ASP.NET Core 静态资源的打包与压缩
    算法
    字符串反转
    js 获取随机数
    AspNetCore MVC 跨域
    add digits
    1-bit and 2-bit Characters
    删除字符串中出现次数最少的字符
    洗牌
    哈夫曼编码
  • 原文地址:https://www.cnblogs.com/719666a/p/9649338.html
Copyright © 2011-2022 走看看