POJ 3146 建图求有向图的最小树形图
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define inf 0x3f3f3f3f
#define PI acos(-1.0)
typedef long long ll;
const int maxn=110;
int n,m;
double mp[maxn][maxn],x[maxn],y[maxn];
double zhuliu()
{
bool vis[maxn],flag[maxn];
int pre[maxn];
double sum=0;
for(int i=0;i<n;i++)
{
flag[i]=false;
mp[i][i]=inf;
}
pre[0]=0;
int i,j,k;
while(true)
{
for(i=1;i<n;i++)
{
if(flag[i])
continue;
pre[i]=i;
for(j=0;j<n;j++)
if(!flag[j]&&mp[j][i]<mp[pre[i]][i])
pre[i]=j;
if(pre[i]==i)
return -1;
}
for(i=1;i<n;i++)
{
if(flag[i])
continue;
for(j=0;j<n;j++)
vis[j]=false;
vis[0]=true;
j=i;
do
{
vis[j]=true;
j=pre[j];
}while(!vis[j]);
if(!j)
continue;
i=j;
do
{
sum+=mp[pre[j]][j];
j=pre[j];
}while(j!=i);
j=i;
do
{
for(k=0;k<n;k++)
if(!flag[k]&&mp[k][j]<inf&&k!=pre[j])
mp[k][j]-=mp[pre[j]][j];
j=pre[j];
} while(j!=i);
for(j=0;j<n;j++)
{
if(j==i)
continue;
for(k=pre[i];k!=i;k=pre[k])
{
if(mp[k][j]<mp[i][j])
mp[i][j]=mp[k][j];
if(mp[j][k]<mp[j][i])
mp[j][i]=mp[j][k];
}
}
for(j=pre[i];j!=i;j=pre[j])
flag[j]=true;
break;
}
if(i==n)
{
for(i=1;i<n;i++)
if(!flag[i])
sum+=mp[pre[i]][i];
break;
}
}
return sum;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mp[i][j]=inf;
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
for(int i=0;i<n;i++)
cin >> x[i] >> y[i];
for(int i=0;i<m;i++)
{
int a,b;
cin >> a >> b;
a--,b--;
double dis=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
mp[a][b]=dis;
}
double sum=zhuliu();
if(sum==-1)
puts("poor snoopy");
else
printf("%.2f\n",sum);
}
return 0;
}