hdu 1827强连通分量

原题链接

题意是有一堆人,和若干关系(单向),你假如选择了一个人,那么其他可以传递的都不需要花费就可以得到。。问最小花费和最少选择人数。。


是一个求强连通的题目,因为如果我们把强连通分量缩点了以后,那么其实就是要把入度为0的都选了就可以,注意如果入度为0的是一个缩点就再枚举找一下里面最小的。。


接下来就是很显然了,这里套用kuangbin的模板。。第一次做强连通,没有想到缩点,用了个奇怪的姿势水过。。。后来想了想应该是错误的?大概是数据比较弱。


ac代码(可能有错误,主要练习一下 tarjan。。。


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int n,m,a,b;
const int MAXN = 1005;
const int MAXM = 2005;
vector<int> E[MAXN];
struct Edge{
    int to,next;
} edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top,scc;
bool Instack[MAXN];
int num[MAXN];
void addedge(int u,int v){
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void Tarjan(int u){
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    for(int i = head[u]; i != -1; i = edge[i].next){
        v = edge[i].to;
        if( !DFN[v] ){
            Tarjan(v);
            if( Low[u] > Low[v] )Low[u] = Low[v];
        }
        else if(Instack[v] && Low[u] > DFN[v])    Low[u] = DFN[v];
    }
    if(Low[u] == DFN[u]){
        scc++;
        do{
            v = Stack[--top];
            Instack[v] = false;
            Belong[v] = scc;
            num[scc]++;
        }
        while( v != u);
    }
}
void solve(int N){
    memset(DFN,0,sizeof(DFN));
    memset(Instack,false,sizeof(Instack));
    memset(num,0,sizeof(num));
    Index = scc = top = 0;
    for(int i = 1; i <= N; i++)   if(!DFN[i])    Tarjan(i);
}
void init(){
    tot = 0;
    memset(head,-1,sizeof(head));
}

int arr[MAXN];
int vis[MAXN];
vector<int> be[MAXN];
pair<int,int> in[MAXN];
void dfs(int x){
    vis[x]=1;
    for(int i=0;i<E[x].size();i++){
        if(!vis[E[x][i]])
            dfs(E[x][i]);
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m)){
        init();
        memset(in,0,sizeof(in));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=n;i++) E[i].clear();
        for(int i=0;i<=n;i++) be[i].clear();
        for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
        for(int i=1;i<=n;i++) in[i].second=i;
        for(int i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            addedge(a,b);
            E[a].push_back(b);
            ++in[b].first;
        }
        solve(n);
        sort(in+1,in+n+1);
        int ans=0,cnt=0,ad=0;
        for(int i=1;i<=n;i++){
            be[Belong[i]].push_back(i);
        }
        for(int i=1;i<=n;i++){
            if(vis[in[i].second]==1||(in[i].first!=0&&num[Belong[in[i].second]]==1))
                continue;
            ++cnt;
            ad=arr[in[i].second];
            for(int j=0;j<be[Belong[in[i].second]].size();j++){
                ad=min(ad,arr[be[Belong[in[i].second]][j]]);
            }
            ans+=ad;
            dfs(in[i].second);
        }
        printf("%d %d
",cnt,ans);
    }
    return 0;
}




原文地址:https://www.cnblogs.com/zhangxianlong/p/10672563.html