hdu2121 最小树形图的虚根
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu2121 最小树形图的虚根相关的知识,希望对你有一定的参考价值。
/*
最小树形图的第二题,终于有了一些理解
具体看注释
*/
/* 无定根的最小树形图 建立虚root 每次只找最短的那条入边 最小树形图理解: 第一步:寻找最短弧集E:扫一遍所有的边,找到每个点权值最小的入边,这一步会产生环 第二步:对每个点 i 找环:通过第一步记录的前驱找环,如果找到了原点或退到了另一个环,点i找环失败 第三步:缩点,缩点就是染色,把每个环内的点染上同一种颜色,每个环内点打上同一个id 第四步:更新一次边集:如果一条边连接两个不同颜色的点,就该边这条边的权值 重复以上四步。 最小树形图的root:root不需要入边 最小树形图的实质是最小生成树,所以用贪心的思想解决,但是贪心找入边时会生产环(第一步) 因此还得找另外一条边连到那个环中,才能解决这个环(第四步) 不定根确定根需要加一个虚根,由虚根为超级源点建立最小生成树, 这样由超级源点出发到达的第一个点就是实际最小生成树的根 虚根和每条边链接一条虚边,其权值要大于实根的和,以此判断是否连了两条虚边(建图失败) 如何找到那个实根:在不断形成环的过程中,会最先有一个点最先和虚根相连,这个点就是实根(实根是不需要入边的,但是在加了虚根后,实根不再是根) 贪心思想保证第一个和虚根链接的必定是实根 */ #include<iostream> #include<cstring> #include<cstdio> #define ll long long #define MAXN 1005 #define INF 0x3f3f3f using namespace std; struct Edge{ ll u,v,cost; }edge[MAXN*MAXN]; ll pos; int pre[MAXN],id[MAXN],visit[MAXN]; ll in[MAXN]; ll zhuliu(int root,int n,int m){ int res=0; int u,v; while(1){ for(int i=0;i<n;i++) in[i]=INF; for(int i=0;i<m;i++) if(edge[i].u!=edge[i].v && edge[i].cost<in[edge[i].v]){ in[edge[i].v]=edge[i].cost; pre[edge[i].v]=edge[i].u; if(edge[i].u==root) pos=i; } for(int i=0;i<n;i++) if(i!=root && in[i]==INF) return -1; int tn=0; memset(id,-1,sizeof id); memset(visit,-1,sizeof visit); in[root]=0; for(int i=0;i<n;i++){ res+=in[i]; v=i; while(visit[v]!=i && id[v]==-1 && v!=root){ visit[v]=i; v=pre[v]; } if(v!=root && id[v]==-1){ for(int u=pre[v];u!=v;u=pre[u]) id[u]=tn; id[v]=tn++; } } if(tn==0) break;//已经没有环了 for(int i=0;i<n;i++) if(id[i]==-1) id[i]=tn++; for(int i=0;i<m;i++){//第四步,更新一次边集 int u=edge[i].u; int v=edge[i].v; edge[i].u=id[u]; edge[i].v=id[v]; if(id[u] != id[v]) edge[i].cost-=in[v]; } n=tn; root=id[root]; } return res; } int main(){ ll n,m; while(scanf("%lld%lld",&n,&m)==2){ ll sum=0; for(ll i=0;i<m;i++){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost); edge[i].u++;edge[i].v++; sum+=edge[i].cost; } int root=n,tot=m;//加入虚根 for(ll i=m;i<n+m;i++){ edge[i].u=0; edge[i].v=i-m+1; edge[i].cost=sum+1; } ll ans=zhuliu(0,n+1,n+m); if(ans==-1 || ans-(sum+1)>=sum+1) printf("impossible "); else printf("%lld %lld ",ans-(sum+1),pos-m); } return 0; }
以上是关于hdu2121 最小树形图的虚根的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 4009 Transfer water(最小树形图)
HDU - 2121 Ice_cream’s world II 无根最小树形图