畅通工程系列问题题解(HDU 1233 1863 1875 1879)
2016-04-07 21:49
537 查看
HDU 1233
krusal
HDU 1863
krusal
hdu 1875
代码一 krusal 100+ms
HDU 1879
krusal+并查集
krusal
#include <iostream> #include <cstring> #include <algorithm> using namespace std; #define maxnum 5051 int n,line;//sum为最小权之和,n为顶点个数,line为边数 int cnt; int par[maxnum]; double sum; struct node { int u,v; double w; }list[maxnum]; int cmp(node a,node b) { return a.w < b.w; } int find(int x)//并查集的路径压缩 { if(par[x] == -1) return x; return par[x] = find(par[x]); } void kruskal() { int i,j; sort(list,list+line,cmp); for(i=0,sum=0;i<line;i++) { int x = find(list[i].u); int y = find(list[i].v); if(x != y) { sum += list[i].w; cnt++; par[x] = y; } if(cnt == n-1) break; } } int main() { int i,j; int vis; double len; int t; while(scanf("%d",&n),n) { memset(par,-1,sizeof(par)); line = n*(n-1)/2; for(i=0;i<line;i++) { scanf("%d%d%lf",&list[i].u,&list[i].v,&list[i].w); } cnt=0; kruskal(); cout<<sum<<endl; } return 0; }
HDU 1863
krusal
#include <iostream> #include <queue> #include <map> #include <cstring> #include <algorithm> using namespace std; #define maxnum 105 int sum,n,line;//sum为最小权之和,n为顶点个数,line为边数 int u[maxnum],v[maxnum],w[maxnum],r[maxnum],p[maxnum];//u起点,v终点,w权值 int cmp(const int i,const int j) { return w[i] < w[j]; } int find(int x)//并查集的路径压缩 { return p[x]==x?x:p[x]=find(p[x]); } int kruskal() { int i,j,k; int cnt = 0; for(i=0;i<line;i++) r[i] = i; for(i=0;i<n;i++) p[i] = i; sort(r,r+line,cmp); for(i=0,sum=0;i<line;i++) { int x = find(u[r[i]]); int y = find(v[r[i]]); if(x != y) { sum += w[r[i]]; cnt++; p[x] = y; } } if(cnt != n-1) sum = 0; return sum; } int main() { int i,j,k; int len; int t,s,d,p,q; while(cin>>line>>n,line) { for(i=0;i<line;i++) { cin>>u[i]>>v[i]>>w[i]; } t = kruskal(); if(t) cout<<t<<endl; else cout<<"?"<<endl; } return 0; }
hdu 1875
代码一 krusal 100+ms
#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; int n;//sum为最小权之和,n为顶点个数,line为边数 int cnt; int par[101]; double sum; struct node { int u; int v; double w; }list[6000]; struct node2 { double u,v; }list2[101]; int cmp(node a,node b) { return a.w < b.w; } int find(int x)//并查集的路径压缩 { if(par[x] == -1) return x; return par[x] = find(par[x]); } double kruskal(int line) { int i,j; sort(list,list+line,cmp); for(i=0,sum=0;i<line;i++) { int x = find(list[i].u); int y = find(list[i].v); if(x != y) { sum += list[i].w; cnt++; par[x] = y; } if(cnt == n-1) return sum; } return 0; } int main() { int i,j,N,k,kk; int vis,line; int len; int p,q; double bian,t; scanf("%d",&N); while(N--) { scanf("%d",&n); memset(par,-1,sizeof(par)); for(i=0,k=0;i<n;i++) { scanf("%lf%lf",&list2[i].u,&list2[i].v); for(j=0;j<i;j++) { bian = sqrt(pow(fabs(list2[j].u-list2[i].u),2.0)+fabs(pow(list2[j].v-list2[i].v,2.0))); if(bian >= 10 && bian <= 1000) { list[k].u = j+1; list[k].v = i+1; list[k++].w = bian; } } } cnt = 0; t = kruskal(k); if(t) printf("%.1lf\n",t*100); else cout<<"oh!"<<endl; } return 0; }代码二Prim 优先队列 60+ms
#include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; int n;//sum为最小权之和,n为顶点个数,line为边数 int cnt; int par[101]; int link[101][101]; double c[101][101]; int yiwei[101]; int vis[6001]; double sum; struct node { int u; int v; double w; }; struct node2 { double u,v; }list2[101]; bool operator < (const node &a,const node &b) { return a.w > b.w; } int prim(int s) { int i,j,k,m,t,u,total; memset(vis,0,sizeof(vis)); priority_queue <node> qq; struct node nn; total = 1; vis[s] = 1; sum = 0; while(total < n) { for(i=1;i<link[s][0];i++) { if(!vis[link[s][i]]) { nn.u = s; nn.v = link[s][i]; nn.w = c[s][nn.v]; qq.push(nn); } } while(!qq.empty() && vis[qq.top().v])//遇到顶点和集合外的顶点没有相连的 qq.pop();//刚巧这个点作为终点是最短的,因为这个顶点没背标记过,所以会错误的计入在内 if(qq.empty()) break; nn = qq.top(); s = nn.v; sum += nn.w; vis[s] = 1;//标记为集合内的元素 qq.pop(); total++; } if(total == n) return 1; else return 0; } int main() { int i,j,N,k,kk; int vis,line; int len; int p,q; double bian,t; scanf("%d",&N); while(N--) { scanf("%d",&n); memset(par,-1,sizeof(par)); for(i=1,k=0;i<=n;i++) { link[i][0] = 1; scanf("%lf%lf",&list2[i].u,&list2[i].v); for(j=1;j<i;j++) { bian = sqrt(pow(fabs(list2[j].u-list2[i].u),2.0)+fabs(pow(list2[j].v-list2[i].v,2.0))); if(bian >= 10 && bian <= 1000) { c[j][i] = c[i][j] = bian; link[i][link[i][0]++] = j; link[j][link[j][0]++] = i; } } } cnt = 0; kk = prim(1); if(kk) printf("%.1lf\n",sum*100); else cout<<"oh!"<<endl; } return 0; }
HDU 1879
krusal+并查集
#include <iostream> #include <cstring> #include <algorithm> using namespace std; #define maxnum 5051 int n;//sum为最小权之和,n为顶点个数,line为边数 int cnt; int par[maxnum]; int sum; struct node { int u,v; double w; }list[maxnum]; struct node2 { int u,w; }list2[maxnum]; int cmp(node a,node b) { return a.w < b.w; } int find(int x)//并查集的路径压缩 { if(par[x] == -1) return x; return par[x] = find(par[x]); } int kruskal(int line) { int i,j; sort(list,list+line,cmp); for(i=0,sum=0;i<line;i++) { int x = find(list[i].u); int y = find(list[i].v); if(x != y) { sum += list[i].w; cnt++; par[x] = y; } if(cnt == n-1) return sum; } return 0; } int fun(int kk) { int i; for(i=0;i<kk;i++) { int x = find(list2[i].u); int y = find(list2[i].w); if(x != y) { cnt++; par[x] = y; } if(cnt == n-1) return 1; } return 0; } int main() { int i,j,k,kk; int vis,line; int len; int t,p,tt,q; while(scanf("%d",&n),n) { k = kk = 0; memset(par,-1,sizeof(par)); line = n*(n-1)/2; for(i=0;i<line;i++) { scanf("%d%d%d%d",&p,&q,&len,&vis); if(vis) { list2[kk].u = p; list2[kk++].w = q; } else { list[k].u = p; list[k].v = q; list[k++].w = len; } } cnt=t=tt=0; if(kk) tt = fun(kk); if(tt) cout<<"0"<<endl; else cout<<kruskal(k)<<endl; } return 0; }
相关文章推荐
- 代码优化:将重复代码封装成函数(2)
- C++实现——杨辉三角
- SharedPreferences 与Editor
- Java判断一个时间是否在另一个时间段内
- 三峰记
- 代码优化:重复代码封装成函数
- HTML基础(四)
- 周总结
- java中的static作用
- java笔记5
- php加载memcache模块
- BZOJ4027: [HEOI2015]兔子与樱花
- opencv轮廓检测之椭圆检测-----算法篇(8) Hough transformation检测椭圆
- Codeforces Round #346 (Div. 2) B. Qualifying Contest
- mac 如何显示隐藏文件和.点开头文件?
- 生成1-N的排列
- 返回一个二维整数数组中最大联通子数组的和
- 线程 1
- PAT 1006. 换个格式输出整数 (15)
- CCF-201512-3 画图