HDU 3072 Intelligence System 强连通缩点

来源:互联网 发布:126邮箱ssl协议端口号 编辑:程序博客网 时间:2024/05/22 02:16

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=3072

题意

给定一个有向有权图,问从0点出发能够访问到其他所有点所需的最小花费,在同一个连通分量中的点访问时不需要加上权值。

思路

很明显是要tarjan缩点了。然后求DAG中的最小树形图?

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<string>#include<queue>#include<stack>#include<set>#include<map>#define ll long longusing namespace std;const int INF = ( 2e9 ) + 2;const ll maxn = 50010;const int maxm = 100010;struct edge{    int u,v,w,next;} e[maxm];vector<edge> vec;int head[maxn];int tot;int dfn[maxn],low[maxn],Stack[maxn],Belong[maxn];bool Instack[maxn];int In[maxn];int f[maxn];int index,top,scc;int Find(int x){    return f[x]==x?x:Find(f[x]);}void add(int u,int v,int w){    e[tot].u=u;    e[tot].v=v;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot++;}void tarjan(int u){    dfn[u]=low[u]=++index;    Instack[u]=1;    Stack[top++]=u;    for(int i=head[u]; i!=-1; i=e[i].next)    {        int v=e[i].v;        if(!dfn[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else if(Instack[v])            low[u]=min(low[u],low[v]);    }    if(dfn[u]==low[u])    {        int x;        scc++;        do        {            x=Stack[--top];            Instack[x]=0;            Belong[x]=scc;        }        while(x!=u);    }}bool cmp(edge a,edge b){    return a.w<b.w;}int Kruscal(){    int ret=0,cnt=0;    sort(vec.begin(),vec.end(),cmp);    for(int i=1;i<=scc;i++)f[i]=i;    memset(In,0,sizeof(In));    for(int i=0,L=vec.size();i<L;i++)    {        int u=vec[i].u,v=vec[i].v,w=vec[i].w;        int xx=Find(u);        int yy=Find(v);        if(xx!=yy&&In[v]==0)        {            f[xx]=yy;            ret+=w;            In[v]=1;            cnt++;        }        if(cnt==scc-1)break;    }    return ret;}int solve(int n){    memset(dfn,0,sizeof(dfn));    top=scc=index=0;    vec.clear();    for(int i=0; i<n; i++)        if(!dfn[i])tarjan(i);    for(int i=0;i<tot;i++)    {        int u=e[i].u,v=e[i].v,w=e[i].w;        if(Belong[u]!=Belong[v])        vec.push_back(edge{Belong[u],Belong[v],w,-1});    }    return Kruscal();}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int u,v,w;        memset(head,-1,sizeof(head));        tot=0;        for(int i=0; i<m; i++)        {            scanf("%d%d%d",&u,&v,&w);            add(u,v,w);        }        printf("%d\n",solve(n));    }}
原创粉丝点击