/* tle十几次,最后发现当i从1开始时,给环赋值时要注意啊! 最小树形图 */ #include<stdio.h> #include<string.h> #include<math.h> #define N 110 #define inf 0x3fffffff #define eps 1e-10 struct node { int u,v; double w; }edge[N*N*2]; double distance (double x,double y,double xx,double yy) { return sqrt(1.0*(x-xx)*(x-xx)+1.0*(y-yy)*(y-yy)); } int visit[N],id[N],pre[N],yong,n; double dis[N]; void addedge(int u,int v,double w){ edge[yong].u=u; edge[yong].v=v; edge[yong++].w=w; } double zhuliu(int root) {//朱刘算法模板 double sum=0; while(1) { int i; for(i=0;i<n;i++) dis[i]=inf; memset(id,-1,sizeof(id)); memset(visit,-1,sizeof(visit)); for(i=0;i<yong;i++) { int u=edge[i].u,v=edge[i].v; if(dis[v]>edge[i].w&&u!=v){ pre[v]=u; dis[v]=edge[i].w; // if(u==root)//记录最后与根节点连接的边 // index=i; } } pre[root]=root; dis[root]=0; for(i=0;i<n;i++) { if(i==root)continue; if(dis[i]==inf)return -1; sum+=dis[i]; } int res=0; for(i=0;i<n;i++) { int v=i; while(visit[v]!=i&&id[v]==-1&&v!=root) { visit[v]=i; v=pre[v]; } if(v!=root&&id[v]==-1) { int u; for(u=pre[v];u!=v;u=pre[u]) id[u]=res; id[v]=res++;//如果下标从1开始不能这么写了 } } if(res==0) break; for(i=0;i<n;i++) { if(id[i]==-1) id[i]=res++;//同上 } for(i=0;i<yong;i++) { int v=edge[i].v; edge[i].u=id[edge[i].u]; edge[i].v=id[edge[i].v]; if(edge[i].u!=edge[i].v) edge[i].w-=dis[v]; } n=res;root=id[root]; } return sum; } int main() { int m,i,j; double k,a[N],b[N]; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) scanf("%lf%lf",&a[i],&b[i]); yong=0; while(m--) { scanf("%d%d",&i,&j); addedge(i-1,j-1,i==j?inf:distance(a[i],b[i],a[j],b[j])); } k=zhuliu(0); if(k<0) printf("poor snoopy\n"); else printf("%.2f\n",k); } return 0; }
/* 下标是1-n; 如果是for(i=1;i<n;i++)还要注意n=res+1。所以模板不能乱改啊 */ #include<stdio.h> #include<string.h> #include<math.h> #define N 110 #define inf 0x3fffffff #define eps 1e-10 struct node { int u,v; double w; }edge[N*N*2]; double distance (double x,double y,double xx,double yy) { return sqrt(1.0*(x-xx)*(x-xx)+1.0*(y-yy)*(y-yy)); } int visit[N],id[N],pre[N],yong,n; double dis[N]; void addedge(int u,int v,double w){ edge[yong].u=u; edge[yong].v=v; edge[yong++].w=w; } double zhuliu(int root) {//朱刘算法模板 double sum=0; while(1) { int i; for(i=1;i<=n;i++) dis[i]=inf; memset(id,-1,sizeof(id)); memset(visit,-1,sizeof(visit)); for(i=0;i<yong;i++) { int u=edge[i].u,v=edge[i].v; if(dis[v]>edge[i].w&&u!=v){ pre[v]=u; dis[v]=edge[i].w; // if(u==root)//记录最后与根节点连接的边 // index=i; } } pre[root]=root; dis[root]=0; for(i=1;i<=n;i++) { if(i==root)continue; if(dis[i]==inf)return -1; sum+=dis[i]; } int res=0; for(i=1;i<=n;i++) { int v=i; while(visit[v]!=i&&id[v]==-1&&v!=root) { visit[v]=i; v=pre[v]; } if(v!=root&&id[v]==-1) { int u; id[v]=++res; for(u=pre[v];u!=v;u=pre[u]) id[u]=res; } } if(res==0) break; for(i=1;i<=n;i++) { if(id[i]==-1) id[i]=++res; } for(i=0;i<yong;i++) { int v=edge[i].v; edge[i].u=id[edge[i].u]; edge[i].v=id[edge[i].v]; if(edge[i].u!=edge[i].v) edge[i].w-=dis[v]; } n=res;root=id[root]; } return sum; } int main() { int m,i,j; double k,a[N],b[N]; while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) scanf("%lf%lf",&a[i],&b[i]); yong=0; while(m--) { scanf("%d%d",&i,&j); addedge(i,j,i==j?inf:distance(a[i],b[i],a[j],b[j])); } k=zhuliu(1); if(k<0) printf("poor snoopy\n"); else printf("%.2f\n",k); } return 0; }
时间: 2024-12-18 19:16:52