HDU 3072 Intelligence System 传递的最小费用

来源:互联网 发布:淘宝京剧服装 编辑:程序博客网 时间:2024/05/16 08:52

题意:人和人之间传递消息,然后一些人到人的传递需要代价,如果一个人可以和另一个人直接或者间接的相互传递,那么他们之间的传递代价忽略不计,问说有人都知道消息的最小代价?


想法:显然tarjan缩点,然后用最小树形图求解,或者小贪心一下,因为最小树形图只跑了一层,显然每一个团体都是从另一个团体得到消息,又因为只有一个入度为0缩点(Believe kzc_tc’s working! There always is a way for him to communicate with all other intelligence personnel.),那么只要得到可以传送到这个团体的所有代价中取出最小的即可。


#include<iostream>#include<cstring>#include<stack>#include<cstdio>#define INF 0x7ffffff#define mm(x) memset(x,0,sizeof(x))using namespace std;const int N=50000+9;const int M=100000+9;stack<int>s;struct node{    int to,next;    int w;}G[M];struct edge{    int u,v,w;}NG[M];int indegree[N];int instack[N],paint[N],col,index,dfn[N],low[N];int head[N],cnt,Ncnt;class tarjan{    public:        int MIN(int a,int b)        {            if(a<b) return a;            return b;        }        void Init()        {            while(!s.empty()) s.pop();            mm(instack);            mm(paint);            mm(dfn);            mm(low);            mm(indegree);            index=1;            col=0;            memset(head,-1,sizeof(head));            cnt=0;            Ncnt=0;        }        void add(int a,int b,int c)        {            G[cnt].to=b;            G[cnt].w=c;            G[cnt].next=head[a];            head[a]=cnt++;        }        void Nadd(int a,int b,int c)        {            NG[Ncnt].u=a;            NG[Ncnt].v=b;            NG[Ncnt++].w=c;        }        void Tarjan(int u)        {            dfn[u]=low[u]=index++;            instack[u]=1;            s.push(u);            for(int i=head[u];i+1;i=G[i].next)            {                int v=G[i].to;                if(!dfn[v])                {                    Tarjan(v);                    low[u]=MIN(low[u],low[v]);                }                else if(instack[v])                {                    low[u]=MIN(low[u],dfn[v]);                }            }            if(low[u]==dfn[u])            {                int k=s.top();                while(k!=u)                {                    s.pop();                    paint[k]=col;                    instack[k]=0;                    k=s.top();                }                s.pop();                paint[u]=col;                instack[u]=0;                col++;            }        }        void build_NG(int n)        {            for(int i=0;i<n;i++)            {                for(int j=head[i];j+1;j=G[j].next)                {                    int u=i,v=G[j].to;                    if(paint[u]!=paint[v])                    {                        Nadd(paint[u],paint[v],G[j].w);                    }                }            }        }}pre_deal;__int64 directed_mst(int root,int nv,int ne){    __int64 res=0;    int in[N],pre[N];    int id[N],vis[N];    while(true)    {        //==找最小入边==         for(int i=0;i<nv;i++)        {            in[i]=INF;        }        for(int i=0;i<ne;i++)        {            int u=NG[i].u;            int v=NG[i].v;            if(NG[i].w<in[v]&&u!=v)            {                pre[v]=u;                in[v]=NG[i].w;            }        }        for(int i=0;i<nv;i++)        {            if(i==root) continue;            if(in[i]==INF) return -1;        }        //==找有向圈==        int cntnode=0;        in[root]=0;        memset(id,-1,sizeof(id));        memset(vis,-1,sizeof(vis));        for(int i=0;i<nv;i++)        {            int v=i;            res+=in[i];            while(vis[v]!=i&&id[v]==-1&&v!=root)            {                vis[v]=i;                v=pre[v];            }            if(id[v]==-1&&v!=root)            {                for(int u=pre[v];u!=v;u=pre[u])                {                    id[u]=cntnode;                }                id[v]=cntnode++;            }        }         if(cntnode==0) break;        for(int i=0;i<nv;i++)        {            if(id[i]==-1)             {                id[i]=cntnode++;            }        }        //==缩点,重新标记==        for(int i=0;i<ne;i++)        {            int v=NG[i].v;            NG[i].u=id[NG[i].u];            NG[i].v=id[NG[i].v];            if(NG[i].u!=NG[i].v)            {                NG[i].w-=in[v];            }        }         nv=cntnode;        root=id[root];    }    return res;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        int root;        pre_deal.Init();        while(m--)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            indegree[b]++;            pre_deal.add(a,b,c);        }        for(int i=0;i<n;i++)        {            if(!dfn[i])            pre_deal.Tarjan(i);        }        int nv=col--;        pre_deal.build_NG(n);        /*cout<<"col="<<col<<endl;        cout<<"Ncnt="<<Ncnt<<endl;        cout<<"------NG------"<<endl;        for(int i=0;i<Ncnt;i++)        {            cout<<NG[i].u<<"-->"<<NG[i].v<<"的价值"<<NG[i].w<<endl;        }        cout<<"根是:"<<paint[0]<<endl;*/         for(int i=0;i<n;i++)        {            if(indegree[i]==0)            {                root=i;                break;            }        }        __int64 ans=directed_mst(paint[root],nv,Ncnt);        printf("%I64d\n",ans);    }    return 0;}

0 0