zoukankan      html  css  js  c++  java
  • UESTC 901 方老师抢银行 --Tarjan求强连通分量

    思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大。所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个DAG(有向无环图),然后跑一遍DFS,不断加上遍历点的权值,如果到了网吧,则更新一遍答案,因为可以出去了。

    求强连通分量时,如果low[u] == dfn[u],说明形成了一个新的强连通分量,且根为u。具体求强连通分量见:http://www.cnblogs.com/whatbeg/p/3776422.html

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    using namespace std;
    #define N 100007
    
    struct Edge
    {
        int v,next;
    }G[3*N],G2[3*N];
    
    int first[3*N],first2[3*N],low[N],dfn[N];
    int instk[N],bel[N],coin[N],iswb[N],wb[N],coin2[N];
    int tot,tot2,n,m,Time,cnt,P,K,res;
    stack<int> stk;
    
    void addedge(Edge *G,int& tot,int *first,int u,int v)
    {
        G[tot].v = v;
        G[tot].next = first[u];
        first[u] = tot++;
    }
    
    void Tarjan(int u)
    {
        low[u] = dfn[u] = ++Time;
        stk.push(u);
        instk[u] = 1;
        for(int i=first[u];i!=-1;i=G[i].next)
        {
            int v = G[i].v;
            if(!dfn[v])   //树边
            {
                Tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(instk[v])  //回边
                low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u])
        {
            cnt++;
            int v;
            do
            {
                v = stk.top();
                stk.pop();
                if(iswb[v])
                    wb[cnt] = 1;
                instk[v] = 0;
                coin2[cnt] += coin[v];
                bel[v] = cnt;
                if(v == P)
                    P = cnt;
            }while(u != v);
        }
    }
    
    void dfs(int u,int sum)
    {
        sum += coin2[u];
        if(wb[u])
            res = max(res,sum);
        for(int i=first2[u];i!=-1;i=G2[i].next)
        {
            int v = G2[i].v;
            dfs(v,sum);
        }
    }
    
    int main()
    {
        int i,j,u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(first,-1,sizeof(first));
            memset(first2,-1,sizeof(first2));
            memset(G,0,sizeof(G));
            memset(G2,0,sizeof(G2));
            memset(iswb,0,sizeof(iswb));
            memset(wb,0,sizeof(wb));
            memset(instk,0,sizeof(instk));
            memset(bel,-1,sizeof(bel));
            memset(coin2,0,sizeof(coin2));
            memset(low,0,sizeof(low));
            memset(dfn,0,sizeof(dfn));
            tot = tot2 = 0;
            Time = cnt = 0;
            while(!stk.empty())
                stk.pop();
            for(i=0;i<m;i++)
            {
                scanf("%d%d",&u,&v);
                addedge(G,tot,first,u,v);
            }
            for(i=1;i<=n;i++)
                scanf("%d",&coin[i]);
            scanf("%d",&P);
            scanf("%d",&K);
            for(i=0;i<K;i++)
            {
                scanf("%d",&v);
                iswb[v] = 1;
            }
            for(v=1;v<=n;v++)  //Tarjan求强连通分量
            {
                if(!dfn[v])
                    Tarjan(v);
            }
            for(i=1;i<=n;i++)   //重建为一个DAG
            {
                for(j=first[i];j!=-1;j=G[j].next)
                {
                    v = bel[G[j].v];
                    u = bel[i];
                    if(u != v)  //如果相连点不是一个连通分量
                        addedge(G2,tot2,first2,u,v);  //建桥
                }
            }
            res = -1;
            dfs(P,0);
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    redis 配置文件说明
    Python 详解命令行解析
    Python 的字符编码
    pt-online-schema-change utf8mb4 错误解决方法【转】
    [MySQL 5.6] Innodb新特性之export/import 表文件
    查找数据库大小和表大小
    MySQL 增删列
    使用MySQL Shell创建MGR
    Qingcloud_MySQL Plus(Xenon) 高可用搭建实验
    MySQL事务提交流程
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3765628.html
Copyright © 2011-2022 走看看