才知道有向图还有最小生成树一说,磨磨蹭蹭搞了半天,范了个很SB的错误,改后总算是过了。。。
ACcode:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int NS=110;
const double INF=1e9;
struct Point
{
double x,y;
void input(){
scanf("%lf %lf",&x,&y);
}
}p[NS];
struct Edge{
int u,v;
double w;
Edge(){}
Edge(int _u,int _v,double _w){
u=_u,v=_v,w=_w;
}
}edge[NS*NS];
int n,m;
double dist(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int pre[NS],id[NS],vis[NS];
double in[NS];
double solve(int rt,int nv,int ne)
{
double ret=0.0;
while(true)
{
int cnt=0;
for (int i=0;i<nv;i++)
in[i]=INF,id[i]=vis[i]=-1;
memset(id,-1,sizeof(id));
memset(vis,-1,sizeof(vis));
for (int i=0;i<ne;i++)
{
int u=edge[i].u;
int v=edge[i].v;
double w=edge[i].w;
if (u!=v && v!=rt && w<in[v])
{
in[v]=w;
pre[v]=u;
}
}
for (int i=0;i<nv;i++)
if (i!=rt && in[i]==INF)
return (-1.0);
in[rt]=0.0;
for (int i=0;i<nv;i++)
{
ret+=in[i];
if (id[i]==-1)
{
int v=i;
while ( v!=rt && vis[v]!=i && id[v]==-1)
{
vis[v]=i;
v=pre[v];
}
if ( v!=rt && id[v]==-1 )
{
for (int u=pre[v];u!=v;u=pre[u])
{
id[u]=cnt;
}
id[v]=cnt++;
}
}
}
if (!cnt) break;
for (int i=0;i<nv;i++)
if (id[i]==-1)
id[i]=cnt++;
for (int i=0;i<ne;i++)
{
int u=edge[i].u;
int v=edge[i].v;
edge[i].u=id[u];
edge[i].v=id[v];
if (id[u]!=id[v])
{
edge[i].w-=in[v];
}
}
nv=cnt;
rt=id[rt];
}
return ret;
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
for (int i=0;i<n;i++)
p[i].input();
for (int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u--,v--;
double w=dist(p[u],p[v]);
if (u==v) w=INF;
edge[i]=Edge(u,v,w);
}
double ans=solve(0,n,m);
if (ans>=0.0)
printf("%.2f\n",ans);
else
printf("poor snoopy\n");
}
return 0;
}