POJ 3164 Command Network(最小树形图模板题)
最小树形图
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> #include <vector> #include <string> using namespace std; typedef long long LL; const int maxn =100+5; const int maxe = 15000+5; const int INF = 460002326; const int mod = 1000000009; double map[maxn][maxn]; double zhuliu(int n) { bool visit[maxn]; bool flag[maxn];//缩点标记为ture,则该点已经被缩掉,否则依然存在 int pre[maxn]; double sum=0; int i,j,k; for(i=0; i<n; i++) { flag[i]=false; map[i][i]=INF; } pre[0]=0; while(true) { //求最短弧集合E0 for(i=1; i<n; i++) { if(flag[i]) continue; pre[i]=i; for(j=0; j<n; j++) { if(!flag[j]&&map[j][i]<map[pre[i]][i]) pre[i]=j; } if(pre[i]==i) return -1; } //检查E0 for(i=1; i<n; i++) { if(flag[i]) continue; //从当前点开始找环 for(j=0; j<n; j++) visit[j]=false; visit[0]=true; j=i; do { visit[j]=true; j=pre[j]; } while(!visit[j]); if(!j) continue; //没有找到环 //收缩G中的有向环 i=j; ///将整个环的权值保存,累计入原图的最小树形图 do { sum+=map[pre[j]][j]; j=pre[j]; } while(j!=i); j=i; //对与环上的点有关的边,修改边权 do { for(k=0; k<n; k++) { if(!flag[k]&&map[k][j]<INF&&k!=pre[j]) map[k][j]-=map[pre[j]][j]; } j=pre[j]; } while(j!=i); //缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i for(j=0; j<n; j++) { if(j==i) continue; for(k=pre[i]; k!=i; k=pre[k]) { if(map[k][j]<map[i][j]) map[i][j]=map[k][j]; if(map[j][k]<map[j][i]) map[j][i]=map[j][k]; } } //标记环上其他的点为被缩掉 for(j=pre[i]; j!=i; j=pre[j]) flag[j]=true; //当前环缩点结束,形成新的图G1,跳出继续求G1的最小树形图 break; } //如果所有的点都被检查切没有环存在,现在的环最短弧几何E0就是最小树形图, //累计入sum,算法结束 if(i==n) { for(i=1; i<n; i++) { if(!flag[i]) sum+=map[pre[i]][i]; } break; } } return sum; } double x[maxn],y[maxn]; double mat(int a,int b) { return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])); } int main() { int n,m; //freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0; i<101; i++) for(int j=0; j<101; j++) map[i][j]=INF; for(int i=0; i<n; i++) scanf("%lf%lf",&x[i],&y[i]); for(int i=0; i<m; i++) { int a,b; scanf("%d%d",&a,&b); a--,b--; map[a][b]=mat(a,b); } double ans=zhuliu(n); if(ans<0) puts("poor snoopy"); else printf("%.2lf\n",ans); } return 0; }