HDU 3072 连通分量+最小树形图

来源:互联网 发布:淘宝联盟查找订单号 编辑:程序博客网 时间:2024/06/01 09:02
==注意是有向图==:一个连通分量化为一个点,因为他们之间的cost=0;构成新图之后直接最小树形图。
#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
原创粉丝点击