HDU 1827Summer Holiday (shrink point + tarjan algorithm)

Click here for the topic link! !
Idea: template question. First, all points within the strongly connected components can communicate with each other. Then find out how many strongly connected components are there, treat each strongly connected component as a point, and consider the in-degree of each connected component's contraction point. A zero in-degree means that no other points can be passed to it, so it must Spend money to pass it to him.

#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<map>
#include<string>
#include<functional>
#include<algorithm>
#include<cstring>
#define lk (k<<1)
#define rk (k<<1|1)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e3+10,M=2e3+10;
int low[N],num[N],scc[N],n,m,st[N],top=0,scc_cnt,dfn,a[N],p[N],deg[N];
struct edge{
    
    
    int to,next;
}e[M];
int head[N],cnt=0;
void add(int u,int v){
    
    
    e[++cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
void dfs(int u)
{
    
    
    st[++top]=u;
    num[u]=low[u]=++dfn;
    for(int i=head[u];i;i=e[i].next){
    
    
        int v=e[i].to;
        if(!num[v]){
    
    
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!scc[v]){
    
    
            low[u]=min(low[u],num[v]);
        }
    }
    if(low[u]==num[u]){
    
    
        scc_cnt++;
        while(1){
    
    
            int v=st[top--];
            scc[v]=scc_cnt;
            p[scc_cnt]=min(p[scc_cnt],a[v]);
            if(v==u) break;
        }
    }
}
void tarjan()
{
    
    
    dfn=0;top=0;
    for(int i=1;i<=n;i++){
    
    
        if(!num[i]) dfs(i);
    }
    memset(deg,0,sizeof(deg));
    for(int i=1;i<=n;i++)
    for(int j=head[i];j;j=e[j].next){
    
    
        int v=e[j].to;
        if(scc[i]!=scc[v]){
    
    
            deg[scc[v]]++;
        }
    }
}
int main()
{
    
    
    while(scanf("%d%d",&n,&m)==2){
    
    
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),p[i]=inf;
        memset(head,0,sizeof(head));
        memset(low,0,sizeof(low));
        memset(num,0,sizeof(num));
        memset(scc,0,sizeof(scc));
        cnt=0;scc_cnt=0;
        for(int i=1;i<=m;i++){
    
    
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        tarjan();
        for(int i=1;i<=n;i++)
        {
    
    
            p[scc[i]]=min(p[scc[i]],a[i]);
        }
        int ans=0,tot=0;
        for(int i=1;i<=scc_cnt;i++) if(!deg[i]) ans+=p[i],tot++;
        printf("%d %d\n",tot,ans);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/amazingee/article/details/107845230