最小树形图
#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;
}