poj3164 (朱刘算法 最小树形图)

题目大意:给定n个点坐标,m条有向边,要求最小树形图。

题解:直接上模板,前面打的 vis[v]=i一直把i打成1,一直TLE。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<string>
 6 #include<algorithm>
 7 const double inf=200000000;
 8 struct Point{
 9     int x,y;
10 }p[200005];
11 struct Edge{
12     double w;
13     int u,v;
14 }e[200005];
15 int n,m;
16 double In[200005];
17 int pre[200005],id[105],vis[105];
18 double dis(int i,int j){
19     return sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
20 }
21 double zhuliu(){
22     double ret=0;
23     int u,v,rt=0;
24     while (1){
25         for (int i=0;i<n;i++) In[i]=inf;
26         for (int i=0;i<m;i++){
27             u=e[i].u;
28             v=e[i].v;
29             if (e[i].w<In[v]&&u!=v){
30                 In[v]=e[i].w;
31                 pre[v]=u;
32             }
33         }
34         for (int i=0;i<n;i++){
35             if (i==rt) continue;
36             if (fabs(In[i]-inf)<1e-8) return -1;
37         }
38         int cnt=0;
39         memset(id,-1,sizeof id);
40         memset(vis,-1,sizeof vis);
41         In[rt]=0;
42         for (int i=0;i<n;i++){
43             ret+=In[i];
44             v=i;
45             while (v!=rt&&vis[v]!=i&&id[v]==-1){
46                 vis[v]=i;
47                 v=pre[v];
48             }
49             if (v!=rt&&id[v]==-1){
50                 for (u=pre[v];u!=v;u=pre[u]){
51                     id[u]=cnt;
52                 }
53                 id[v]=cnt++;
54             }
55         }
56         if (cnt==0) break;
57         for (int i=0;i<n;i++){
58             if (id[i]==-1) id[i]=cnt++;
59         }
60         for (int i=0;i<m;i++){
61             u=e[i].u;
62             v=e[i].v;
63             e[i].u=id[u];
64             e[i].v=id[v];
65             if (e[i].u!=e[i].v){
66                 e[i].w-=In[v];
67             }
68         }
69         n=cnt;
70         rt=id[rt];
71     }
72     return ret;
73 }
74 int main(){
75     freopen("poj3164.in","r",stdin);
76         freopen("poj3164.out","w",stdout);
77     while (~scanf("%d%d",&n,&m)){
78         for (int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y);
79         for (int i=0;i<m;i++){
80             scanf("%d%d",&e[i].u,&e[i].v);
81             e[i].u--;e[i].v--;
82             if (e[i].u==e[i].v) e[i].w=inf;
83             else
84             e[i].w=dis(e[i].u,e[i].v);
85         }
86         double t=zhuliu();
87         if (t<0.0) printf("poor snoopy
");
88         else printf("%.2f
",t);
89     }
90 }
黄维大沙茶
原文地址:https://www.cnblogs.com/qzqzgfy/p/5266453.html