HDU

<题目链接>

题目大意:

听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗? 

解题分析:

强连通缩点,再将所有入度为0的强连通分量中最小的价值相加即可。

#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define clr(a,b) memset(a,b,sizeof(a))
const int N = 1e3+10,M = 2e3+10;
int n,m,tot,cnt,scc,top;
int val[N],instk[N],stk[N],dfn[N],low[N],ind[N],outd[N],belong[N],head[N];
struct Edge{
    int to,next;
}edge[M];
vector<int>G[N];
void init(){
    rep(i,0,n)G[i].clear();
    tot=cnt=scc=top=0;
    clr(instk,0);clr(stk,0);clr(dfn,0);clr(low,0);clr(ind,0);clr(outd,0);clr(belong,0),clr(head,-1);
}
void addedge(int u,int v){
    edge[++cnt].to=v,edge[cnt].next=head[u];
    head[u]=cnt;
}
void Tarjan(int u){
    dfn[u]=low[u]=++tot;
    stk[++top]=u;instk[u]=1;
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].to;
        if(!dfn[v]){
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(instk[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        scc++;
        while(true){
            int v=stk[top--];
            instk[v]=0;
            belong[v]=scc;
            G[scc].pb(v);
            if(v==u)break;
        }
    }
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        rep(i,1,n)scanf("%d",&val[i]);
        rep(i,1,m){
            int u,v;scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        rep(i,1,n)
            if(!dfn[i])Tarjan(i);
        rep(u,1,n) for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(belong[u]!=belong[v])
                ind[belong[v]]++,outd[belong[u]]++;
        }
        int ans=0,res=0;
        rep(i,1,scc) if(!ind[i]){
            int mn=1e9;
            rep(j,0,G[i].size()-1){      //遍历该连通块中的所有元素,寻找价值最小的
                int v=G[i][j];
                mn=min(mn,val[v]);
            }
            res++;
            ans+=mn;
        }
        printf("%d %d
",res,ans);
    }
}
原文地址:https://www.cnblogs.com/00isok/p/10765315.html