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;
            }
        }
    }
  • 相关阅读:
    codevs 1115 开心的金明
    POJ 1125 Stockbroker Grapevine
    POJ 2421 constructing roads
    codevs 1390 回文平方数 USACO
    codevs 1131 统计单词数 2011年NOIP全国联赛普及组
    codevs 1313 质因数分解
    洛谷 绕钉子的长绳子
    洛谷 P1276 校门外的树(增强版)
    codevs 2627 村村通
    codevs 1191 数轴染色
  • 原文地址:https://www.cnblogs.com/719666a/p/9649338.html
Copyright © 2011-2022 走看看