朱刘算法与最小树形图
参考:http://hi.baidu.com/yhxhqvnjombfpzq/item/5d93ef69ceb541176895e682
http://hi.baidu.com/lydrainbowcat/item/5fbae3fb9c159c5ec8f33753(看这篇文章有助于理解缩点过程中对于权的处理,非常清晰)
想要自己写可是还是没有写出来,把这位同学的代码抄了一遍,终于弄懂了。。十分感谢。http://blog.sina.com.cn/s/blog_6af663940100ls4e.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<algorithm> #include<math.h> #include<iostream> #include<string.h> using namespace std; #define MAXN 110 #define INF 1000000000 #define clr(a,b); memset(a,b,sizeof(a)); struct Node { double x; double y; }node[MAXN]; int n,m; int tmp; bool visited[MAXN],circle[MAXN]; int pre[MAXN]; double graph[MAXN][MAXN]; inline double dist(int i,int j) { return sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)+(node[i].y-node[j].y)*(node[i].y-node[j].y)); } inline double min(double a,double b) { if(a<b) return a; return b; } void dfs(int u) /*深搜判断是否能够到达每个结点*/ { if(visited[u]) return; visited[u]=true; for(int i=1;i<=n;i++) { if(!visited[i]&&graph[u][i]!=INF) { dfs(i); } } } bool connect() { dfs(1); for(int i=1;i<=n;i++) { if(!visited[i]) return false; } return true; } double zhu_liu() { double ans=0;int i,j,k; clr(circle,0);//如果某点被删除了,那么circle[i]=1 while(1) { //求出除根节点以为每个结点入边的最小值 for(i=2;i<=n;i++) { if(circle[i]) continue; graph[i][i]=INF; //把图中所有的自环都清除,这一点很重要 pre[i]=i; //初始化自己的前一个结点是自己 for(j=1;j<=n;j++) { if(circle[j]) continue; if(graph[j][i]<graph[pre[i]][i]) { pre[i]=j; } } } //遍历找环 for(i=2;i<=n;i++) { if(circle[i]) continue; j=i; clr(visited,false); while(!visited[j]&&j!=1) { visited[j]=true; j=pre[j]; } if(j==1) continue; i=j; //把环的权值都加到ans里 ans+=graph[pre[i]][i]; for(j=pre[i];j!=i;j=pre[j]) { ans+=graph[pre[j]][j]; circle[j]=1; //只用i代表这个环,其他的点都删掉,缩点 } for(j=1;j<=n;j++) { if(circle[j]) continue; if(graph[j][i]!=INF) graph[j][i]-=graph[pre[i]][i]; } for(j=pre[i];j!=i;j=pre[j]) { for(k=1;k<=n;k++) { if(circle[k]) continue; if(graph[j][k]!=INF) graph[i][k]=min(graph[i][k],graph[j][k]); if(graph[k][j]!=INF) graph[k][i]=min(graph[k][i],graph[k][j] - graph[pre[j]][j]); } } break; } if(i>n) { for(j=2;j<=n;j++) { if(circle[j]) continue; ans+=graph[pre[j]][j]; } break; } } return ans; } int main() { int i,j,u,v; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { scanf("%lf%lf",&node[i].x,&node[i].y); } for(i=1;i<=n;i++) for(j=1;j<=n;j++) { graph[i][j]=INF; } while(m--) { scanf("%d%d",&u,&v); graph[u][v]=dist(u,v); } clr(visited,false); if(!connect()) printf("poor snoopy\n"); else printf("%.2f\n",zhu_liu()); } return 0; }