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

    hdu1827 Summer Holiday
    传送门
    题意
    给定一个(n(1leq nleq 1000))个点,(m(1leq mleq 2000))条边的有向图,每个点都有权值,选取一些点,使得这些点可以连接到图中所有的点,计算总权值的最小值
    题解
    强连通分量缩点,将图变成几个(DAG),每个顶点的权值是它所代表的(scc)中所有点的权值最小值,在每个(DAG)中选择所有入度为零的点,计算这些点的权值和

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<cmath>
    #include<ctime>
    #include<climits>
    #include<algorithm>
    #define LL long long
    #define PII pair<int,int>
    #define PLL pair<LL,LL>
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lowbit(x) x&(-x)
    using namespace std;
    
    const int maxn=1010,maxm=2010;
    int n,m,cost[maxn],dfn[maxn],low[maxn],scc[maxn],scccost[maxn],stk[maxn],top,dfscnt,scccnt;
    int in[maxn];
    vector<int> g[maxn];
    
    void tarjan(int u){
        dfn[u]=low[u]=++dfscnt;
        stk[++top]=u;
        for(int v:g[u]){
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!scc[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){
            scccnt++;
            while(1){
                int v=stk[top--];
                scc[v]=scccnt;
                scccost[scccnt]=min(scccost[scccnt],cost[v]);
                if(v==u) break;
            }
        }
    }
    
    int main(){
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
            for(int i=1;i<=n;i++) g[i].clear();
            for(int i=0;i<m;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                g[x].push_back(y);
            }
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(scc,0,sizeof(scc));
            memset(scccost,0x3f,sizeof(scccost));
            memset(in,0,sizeof(in));
            top=dfscnt=scccnt=0;
            for(int i=1;i<=n;i++){
                if(!scc[i]) tarjan(i);
            }
            for(int i=1;i<=n;i++){
                for(int v:g[i]){
                    if(scc[i]!=scc[v]) in[scc[v]]=1;
                }
            }
            int anscnt=0,ans=0;
            for(int i=1;i<=scccnt;i++){
                if(!in[i]){
                    anscnt++;
                    ans+=scccost[i];
                }
            }
            printf("%d %d
    ",anscnt,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    [Poi2000]病毒
    [Zjoi2015]诸神眷顾的幻想乡
    P1663 山
    P1837 单人纸牌
    P6584 重拳出击
    CF460C Present
    10.5 学习笔记
    多项式学习笔记(一) FFT
    NOIP 2020 游记
    uva 经典习题选做(dp专项)
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13616489.html
Copyright © 2011-2022 走看看