模板题,没啥好说的。。
最小树形图的解法见:http://www.cnblogs.com/vongang/archive/2012/07/18/2596851.html
CODE:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 50010 #define INF (min_dis[0]) using namespace std; struct Point{ int x,y; }point[MAX]; int points,edges; int head[MAX],total; int next[MAX],aim[MAX],from[MAX]; double length[MAX]; double min_dis[MAX]; int father[MAX]; int vis[MAX],num[MAX],cnt; inline void Initialize(); inline void Add(int x,int y,double len); inline double Calc(Point a,Point b); double DirectedMST(int root); int main() { while(scanf("%d%d",&points,&edges) != EOF) { Initialize(); for(int i = 1;i <= points; ++i) scanf("%d%d",&point[i].x,&point[i].y); for(int x,y,i = 1;i <= edges; ++i) { scanf("%d%d",&x,&y); if(x != y) Add(x,y,Calc(point[x],point[y])); } double ans = DirectedMST(1); if(ans == -1) puts("poor snoopy"); else printf("%.2lf\n",ans); } return 0; } inline void Initialize() { total = 0; memset(head,0,sizeof(head)); } inline void Add(int x,int y,double len) { next[++total] = head[x]; aim[total] = y; length[total] = len; from[total] = x; head[x] = total; } inline double Calc(Point a,Point b) { return sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y)); } double DirectedMST(int root) { double re = 0; while(1) { memset(min_dis,0x43,sizeof(min_dis)); for(int i = 1;i <= total; ++i) { if(length[i] < min_dis[aim[i]] && from[i] != aim[i]) { min_dis[aim[i]] = length[i]; father[aim[i]] = from[i]; } } for(int i = 1;i <= points; ++i) if(i != root && min_dis[i] == INF) return -1; memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); min_dis[root] = 0; cnt = 0; for(int i = 1;i <= points; ++i) { re += min_dis[i]; int now = i; while(vis[now] != i && !num[now] && now != root) { vis[now] = i; now = father[now]; } if(now != root && !num[now]) { ++cnt; for(int j = father[now];j != now;j = father[j]) num[j] = cnt; num[now] = cnt; } } if(!cnt) break; for(int i = 1;i <= points; ++i) if(!num[i]) num[i] = ++cnt; for(int i = 1;i <= edges; ++i) { if(num[from[i]] != num[aim[i]] && num[aim[i]] <= cnt) length[i] -= min_dis[aim[i]]; from[i] = num[from[i]]; aim[i] = num[aim[i]]; } points = cnt; root = num[root]; } return re; }