HDU 1232 畅通工程 HDU 1874 畅通工程续 HDU 1875 畅通工程再续
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1232
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1874
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1875
畅通工程属于水题,直接用并查集就行,加个路径压缩那就更好。
畅通工程续这道题WA了N次,因为有一个地方没注意到就是一个城镇到另外一个城镇的有多条道路,
所以你一开始就要把最短的道路选出来。我用的是Prim算法思想,只是把集合点到集合点的最短距离改
成集合点到单源点距离,后来发现这种算法又叫Dijkstra算法,0ms AC,貌似比许多人写的Dijkstra算
法时间要少,内存空间占用也小。
畅通工程再续这道题可以采用最小生成树,有Prim算法,Kruskal算法,个人觉得这里Prim算法要优于
Kruskal算法,因为它给出的条件是坐标,那么每条边都要计算,边数为e=n(n-1)/2,时间复杂度为O(elog n),
并没有多大的优化。注意变量类型距离都要是double。
1 /*HDU 1232*/ 2 #include<stdio.h> 3 const int maxn=1000+5; 4 int fa[maxn]; 5 void init(int n) 6 { 7 for(int i=1;i<=n;i++) 8 fa[i]=0; 9 } 10 int find_father(int x) 11 { 12 if(fa[x]==0) 13 return x; 14 fa[x]=find_father(fa[x]); 15 return fa[x]; 16 } 17 void union_father(int x,int y) 18 { 19 int find_a=find_father(x),find_b=find_father(y); 20 if(find_a!=find_b) 21 fa[find_b]=find_a; 22 } 23 int main() 24 { 25 int t; 26 scanf("%d",&t); 27 while(t--){ 28 int n,m,a,b; 29 scanf("%d%d",&n,&m); 30 init(n); 31 for(int i=1;i<=m;i++){ 32 scanf("%d%d",&a,&b); 33 union_father(a,b); 34 } 35 int ans=0; 36 for(int i=1;i<=n;i++) 37 if(fa[i]==0) 38 ans++; 39 printf("%d\n",ans); 40 } 41 return 0; 42 }
1 /*HDU 1874*/ 2 #include<stdio.h> 3 #include<string.h> 4 #define doumin(a,b) (a<b?a:b) 5 #define INF 0x3f3f3f3f 6 const int maxn=200+5;
7 int c[maxn][maxn],closest[maxn],s,t,m; 8 bool flag[maxn]; 9 void prim(int n) 10 { 11 memset(flag,false,sizeof(bool)*(n+1)); 12 flag[s]=true; 13 closest[s]=0; 14 for(int i=0;i<n;i++) 15 if(!flag[i]) 16 closest[i]=c[s][i]; 17 for(int i=1;i<n;i++){ 18 int mincost=INF,j=s; 19 for(int k=0;k<n;k++){ 20 if(mincost>closest[k] && !flag[k]){ 21 mincost=closest[k]; 22 j=k; 23 } 24 } 25 flag[j]=true; 26 for(int k=0;k<n;k++) 27 if(closest[k]>c[k][j]+mincost) 28 closest[k]=c[k][j]+mincost; 29 } 30 } 31 int main() 32 { 33 int n; 34 while(scanf("%d%d",&n,&m)!=EOF){ 35 int u,v,w; 36 for(int i=0;i<n;i++) 37 for(int j=0;j<n;j++) 38 c[i][j]=(i==j?0:INF); 39 for(int i=1;i<=m;i++){ 40 scanf("%d%d%d",&u,&v,&w); 41 c[u][v]=c[v][u]=doumin(c[u][v],w); 42 } 43 scanf("%d%d",&s,&t); 44 prim(n); 45 if(closest[t]>=INF) 46 printf("-1\n"); 47 else 48 printf("%d\n",closest[t]); 49 } 50 return 0; 51 }
1 /*HDU 1875*/ 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<string.h> 6 #define INF 0x3f3f3f3f 7 const int maxn=100+2; 8 int x[maxn],y[maxn]; 9 double lowdist[maxn]; 10 bool s[maxn]; 11 double prim(int n) 12 { 13 double ans=0; 14 s[1]=true; 15 for(int i=2;i<=n;i++){ 16 double t=(x[i]-x[1])*(x[i]-x[1])+(y[i]-y[1])*(y[i]-y[1]); 17 t=sqrt(t); 18 if(t>1000 || t<10) 19 t=INF; 20 lowdist[i]=t; 21 s[i]=false; 22 } 23 for(int i=1;i<n;i++){ 24 double mindist=INF; 25 int j=1; 26 bool flag=true; 27 for(int k=2;k<=n;k++) 28 if(!s[k]) 29 if(mindist>lowdist[k]){ 30 mindist=lowdist[k]; 31 j=k; 32 flag=false; 33 } 34 s[j]=true; 35 if(flag) 36 return -1; 37 ans+=mindist; 38 for(int k=2;k<=n;k++){ 39 if(!s[k]){ 40 double t=(x[k]-x[j])*(x[k]-x[j])+(y[k]-y[j])*(y[k]-y[j]); 41 t=sqrt(t); 42 if(t>1000 || t<10) 43 continue; 44 if(lowdist[k]>t) 45 lowdist[k]=t; 46 } 47 } 48 } 49 return ans; 50 } 51 int main() 52 { 53 int t; 54 scanf("%d",&t); 55 while(t--){ 56 int n; 57 scanf("%d",&n); 58 for(int i=1;i<=n;i++) 59 scanf("%d%d",&x[i],&y[i]); 60 double ansdist=prim(n); 61 if(ansdist<0) 62 printf("oh!\n"); 63 else 64 printf("%0.1f\n",ansdist*100.0); 65 } 66 return 0; 67 }