UVa 11183 定根的最小树形图,模板题

来源:互联网 发布:查看端口监听ipv6 编辑:程序博客网 时间:2024/04/29 05:38

题意:定根的最小树形图

解法:朱刘算法

#include<stdio.h>#include<string.h>#define MAXN 1111#define MAXM 44000#define INF 1000000000struct node{int u,v,w;}e[MAXM];int pre[MAXN],id[MAXN],vis[MAXN],in[MAXN],ans;int n,m,root;bool Directed_MST(int root,int nv,int ne)  //朱刘算法{int i,j,u,v;ans=0;while(1){for(i=0;i<nv;i++) in[i]=INF;for(i=0;i<ne;i++)    //找出每个点入边权值的最小值{u=e[i].u; v=e[i].v;if(e[i].w<in[v]&&u!=v){pre[v]=u; in[v]=e[i].w;}}for(i=0;i<nv;i++)    //有个出了根节点的点找不到入边,则有向图中不存在最小树形图if(i!=root&&in[i]==INF)return 0;int cntNode=0;       //总共有的节点数,随着缩点会改变memset(id,0xff,sizeof(id));  //属于第几个节点memset(vis,0xff,sizeof(vis));//判断是否已经被归入某个节点in[root]=0;for(i=0;i<nv;i++){ans+=in[i];     //计算最小权值和v=i;while(vis[v]!=i&&id[v]==-1&&v!=root)   //找环,将一个环上的点归入一个编号,便于缩点{vis[v]=i; v=pre[v];}if(v!=root&&id[v]==-1)      //找到环{for(u=pre[v];u!=v;u=pre[u])  //将环上的每个点归到一个节点id[u]=cntNode;id[v]=cntNode++;       //一个环代表一个节点,缩点}}if(cntNode==0) break;for(i=0;i<nv;i++)       //记录非环上的节点if(id[i]==-1) id[i]=cntNode++;for(i=0;i<ne;i++)      //缩点,假设连接边的某个节点属于某个环,则将边上记录的改点改为缩点后的点,完成缩点操作{v=e[i].v;e[i].u=id[e[i].u];e[i].v=id[e[i].v];if(e[i].u!=e[i].v)e[i].w-=in[v];}nv=cntNode;      //缩点之后,节点数只有cntNode个root=id[root];}return 1;}int main(){int i,j,u,v,w,cas,T;scanf("%d",&T);for(cas=1;cas<=T;cas++){scanf("%d%d",&n,&m);for(i=0;i<m;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);if(Directed_MST(0,n,m)) printf("Case #%d: %d\n",cas,ans);else printf("Case #%d: Possums!\n",cas);}return 0;}