zoukankan      html  css  js  c++  java
  • CF427C 强连通

    Description

    Your city has n junctions. There are mone-way roads between the junctions. As a mayor of the city, you have to ensure the security of all the junctions.

    To ensure the security, you have to build some police checkposts. Checkposts can only be built in a junction. A checkpost at junction ican protect junction j if either i = j or the police patrol car can go to j from i and then come back to i.

    Building checkposts costs some money. As some areas of the city are more expensive than others, building checkpost at some junctions might cost more money than other junctions.

    You have to determine the minimum possible money needed to ensure the security of all the junctions. Also you have to find the number of ways to ensure the security in minimum price and in addition in minimum number of checkposts. Two ways are different if any of the junctions contains a checkpost in one of them and do not contain in the other.

    Input

    In the first line, you will be given an integer n, number of junctions (1 ≤ n ≤ 105). In the next line, n space-separated integers will be given. The ith integer is the cost of building checkpost at the ith junction (costs will be non-negative and will not exceed 109).

    The next line will contain an integer m (0 ≤ m ≤ 3·105). And each of the next m lines contains two integers ui and vi (1 ≤ ui, vi ≤ nu ≠ v). A pair ui, vi means, that there is a one-way road which goes from ui to vi. There will not be more than one road between two nodes in the same direction.

    Output

    Print two integers separated by spaces. The first one is the minimum possible money needed to ensure the security of all the junctions. And the second one is the number of ways you can ensure the security modulo 1000000007(109 + 7).

    Sample Input

    Input
    3 1 2 3 3 1 2 2 3 3 2
    Output
    3 1




    题意:在每个强连通图中建一个派出所,使总费用最低,并且总费用最低的建法有多少种。
    思路:其实就是强连通,之后每个连通图在找最小费用点,并记录个数,最后把每个连通图的最小费用相加,记得会爆int,
    把每个连通图的最小费用点个数相乘即可;
       我发现自己还是太弱了,我把每个强连通找出来并标记,在查找,后来看看别人的代码,
    其实在Tarjan函数里出栈的时候就可以找到了。真是666666.
    自己AC代码:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef __int64 LL;
    const int maxn = 100009;
    const int maxm = 400009;
    const LL inf = (LL)1<<50;
    const int MOD = 1000000000 + 7;
    struct node
    {
        int v,next;
    }eg[maxm];
    int head[maxn],vis[maxn],sta[maxn],insta[maxn],dfn[maxn],low[maxn],belong[maxn];
    int count[maxn],val[maxn];
    int tot,color,top,n,m,Index;
    
    vector<int>vec[maxn];
    
    void add(int a,int b)
    {
        eg[tot].v = b;
        eg[tot].next = head[a];
        head[a] = tot++;
    }
    
    void init()
    {
        tot = top = color =  Index = 0;
        memset(head,-1,sizeof(head));
        memset(insta,0,sizeof(insta));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(belong,0,sizeof(belong));
        memset(vis,0,sizeof(vis));
    //memset(count,0,sizeof(count));
        for(int i=1;i<maxn;i++)vec[i].clear();
    }
    inline int min(int a,int b){return a < b ? a : b;}
    
    void input()
    {
        int i,a,b;
        for(i=1;i<=n;i++)
            scanf("%d",&val[i]);
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
    }
    
    void Tarjan(int u)
    {
        dfn[u] = low[u] = ++Index;
        sta[top++] = u;
        insta[u] = 1;
        for(int i = head[u];i+1;i=eg[i].next)
        {
            int v = eg[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u] = min(low[u],low[v]);
            }else if(insta[v])
                low[u] = min(low[u],dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            int v ;
            color++;
            do
            {
                v = sta[--top];
                insta[v] = 0;
                belong[v] = color;
            }while(v!=u);
        }
    }
    
    void work()
    {
        int i,j;
        for(i=1;i<=n;i++)
        {
            if(!dfn[i]) Tarjan(i);
        }
    //    printf("color ==%d
    ",color);
        for(int u=1;u<=n;u++)
        {
            for(i=head[u];i+1;i =eg[i].next)
            {
                int v = eg[i].v;
                    int k = belong[u];
                    if(!vis[u])
                        vec[k].push_back(u),vis[u] = 1;
                     k = belong[v];
                    if(!vis[v])
                        vec[k].push_back(v),vis[v] = 1;
            }
        }
        for(i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                int k = belong[i];
                vec[k].push_back(i);
                vis[i] = 1;
            }
        }
        LL cost = 0;
        LL sum = 1;
        for(i=1; i <= color; i++)
        {
            int minnum = 0x7fffffff;
            int count = 0;
            for(j =0;j<vec[i].size();j++)
            {
                
                int v = vec[i][j];
        //    printf(" %d",v);
                minnum = min(minnum,val[v]);
            }
            for(j=0;j<vec[i].size();j++)
            {
                int v = vec[i][j];
                if(val[v] == minnum) count++;
            }
            cost +=minnum;
            sum = sum * count;
            sum %= MOD;
    //        puts("");
        }
        printf("%I64d %I64d
    ",cost,sum);
    }
    int main()
    {
    //    int i,a,b,w;
        while(~scanf("%d",&n))
        {
            init();
            input();
        //    for(int i=1;i<=n;i++)printf("%d  ",val[i]);
            work();
        }
        return 0;
    }

     最后改进代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef __int64 LL;
    const int maxn = 100009;
    const int maxm = 400009;
    const LL inf = (LL)1<<50;
    const LL MOD = 1000000000 + 7;
    struct node
    {
        int v,next;
    }eg[maxm];
    int head[maxn],sta[maxn],insta[maxn],dfn[maxn],low[maxn];
    int val[maxn];
    int tot,color,top,n,m,Index;
    LL cost,produce;
    
    vector<int>vec[maxn];
    
    void add(int a,int b)
    {
        eg[tot].v = b;
        eg[tot].next = head[a];
        head[a] = tot++;
    }
    
    void init()
    {
        tot = top = color =  Index = 0;
        memset(head,-1,sizeof(head));
        memset(insta,0,sizeof(insta));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
    //    memset(belong,0,sizeof(belong));
    //    memset(vis,0,sizeof(vis));
    //memset(count,0,sizeof(count));
        for(int i=1;i<maxn;i++)vec[i].clear();
    }
    inline int min(int a,int b){return a < b ? a : b;}
    
    void input()
    {
        int i,a,b;
        for(i=1;i<=n;i++)
            scanf("%d",&val[i]);
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
    }
    
    
    void Tarjan(int u)
    {
        dfn[u] = low[u] = ++Index;
        sta[top++] = u;
        insta[u] = 1;
        for(int i = head[u];i+1;i=eg[i].next)
        {
            int v = eg[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u] = min(low[u],low[v]);
            }else if(insta[v])
                low[u] = min(low[u],dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            int v ;
        //    color++;
            int minnum = MOD;
            int sum = 0;
            do
            {
                v = sta[--top];
                insta[v] = 0;
        //        belong[v] = color;
                if(minnum == val[v]) sum ++;
                else if(minnum > val[v]) sum = 1,minnum = val[v];     
            }while(v!=u);
            cost +=minnum;
            produce = (produce*sum) % MOD;
            
        }
    }
    
    void work()
    {
        int i;
        cost = 0;
        produce = 1;
        for(i=1;i<=n;i++)
        {
            if(!dfn[i]) Tarjan(i);
        }
        printf("%I64d %I64d
    ",cost,produce);
    
    }
    int main()
    {
    
        while(~scanf("%d",&n))
        {
            init();
            input();
        //    for(int i=1;i<=n;i++)printf("%d  ",val[i]);
            work();
        }
        return 0;
    }
    
    /*
    
    
    
      10
    1 3 2 2 1 3 1 4 10 10
    12
    1 2
    2 3
    3 1
    3 4
    4 5
    5 6
    5 7
    6 4
    7 3
    8 9
    9 10
    10 9
    
    
    
    10
    1 1 1 1 1 1 1 2 2 2
    15
    2 3
    2 4
    4 1
    4 7
    4 10
    4 5
    4 8
    2 6
    3 2
    1 2
    7 2
    10 2
    5 2
    8 2
    6 2
    
      */
  • 相关阅读:
    php 文件下载 重命名
    [转载]北漂一族年终总结:在北京混必备的六大能力
    出去转了一转,便利店......
    来京第一天
    生活脚步,不停地走......
    键盘控制层的移动javascript
    离开告别...重新开始...
    夜未眠,三字诗......
    我喜欢这首歌......
    Foxmail邮件发不出去,都是Mcafee惹得祸
  • 原文地址:https://www.cnblogs.com/BruceNoOne/p/3886789.html
Copyright © 2011-2022 走看看