hdoj 1863 畅通工程【最小生成树,kruskal&&prim】
2015-08-27 18:27
477 查看
畅通工程
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 21867 Accepted Submission(s): 9466
略
[align=left]Sample Input[/align]
3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
[align=left]Sample Output[/align]
3 ?
最小生成树模板题:
kruskal版的最小生成树主要思想是:将所有的边按权(即本题中的两城市的距离)从小到大排序,然后从最小的一个开始查看,(这里用的是并查集的内容),
①若当前最小边连接的两个结点不在一颗树上,则将任意一方合并到另一方上面,然后把这条边的长度累加到总长度上,然后接着查看下一条边,
②若当前最小边连接的两个结点在一棵树上,则放弃这条边,继续查看下一条边,
重复上述步骤,知道查看完所有的边;
已Accept代码【c++提交】
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int per[1010]; void init(int n){ for(int i=1;i<=n;i++) per[i]=i; } struct node{ int s,c,l; }a[10050]; int cmp(node k,node g){ return k.l<g.l; } //-------------------- int find(int x){ // * int r=x; // *** while(r!=per[r]) // * * * r=per[r]; // * return r; // * } // * // * bool join(int x,int y){ // 并查集 int fx=find(x); // * int fy=find(y); // * if(fx!=fy){ // * per[fx]=fy; // * return true; // * * * } // *** return false; // * } //-------------------- int main(){ int n,m,i,j; while(scanf("%d",&n),n){ scanf("%d",&m); init(m); for(i=0;i<n;i++) scanf("%d%d%d",&a[i].s,&a[i].c,&a[i].l); sort(a,a+n,cmp); //从小到大排序 int total=0,sum=0; for(i=0;i<n;i++){ //从最小的开始查看 if(join(a[i].s,a[i].c)){ //判断是否在一颗树上,若不在着则相连,若在,则放弃 total++; //记录已连接的结点的个数 sum+=a[i].l; //记录总长度 } if(total==m-1) //判断是否所有结点都连在一起, break; } if(total==m-1) printf("%d\n",sum); else printf("?\n"); } return 0; }
prim版的最小生成树主要思想是:从所有结点中任意选一个(一般都选编号最小的,加入集合A(即把vis集合中对应的点标记为 "1" )),【haha】然后查看与之连接的 边的长度,把边的长度记录在数组dis中(dis[i]中的序号 对应 边的 另一头 结点 的 编号),选最短的然后连接,累加所连接的边的长度,然后把边另一头的结点 加入集合A(即把这个结点与最开始时的结点相连在一棵树上,为了好描述,这里把新加入集合A的结点统一称为K),然后查看与K相连的边的长度,记录这下变得长度,然后回到【haha】,直到所有结点都加入集合A为止;
【空格为停顿】
【注意1:输入时,要判断是否重边,若重边,取短的】
【注意2:要定义一个数组标记结点是否被查看过,使用前初始化为 零 】
【注意3:dis数组使用前要初始化为无穷大,笔者一般都初始化为INF (#define INF 0x3f3f3f3f)】
已Accept代码【c提交】
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f int n,m; int v[101],dis[101]; int map[101][101]; void prim(){ int i,j,min,pos,total=0; memset(v,0,sizeof(v)); v[1]=1,pos=1; //选 "1" 为初始结点 for(i=1;i<=m;i++) dis[i]=map[1][i]; //记录与"1"线连接的边的长度 for(i=1;i<m;i++){ //【haha】 min=INF; for(j=1;j<=m;j++) if(!v[j]&&min>dis[j]){ //比较边的长度 ,记录最短的 min=dis[j]; pos=j; } total+=min; //累加边的长度 v[pos]=1; //标记为集合A的元素 for(j=1;j<=m;j++) //查看新加入点周围的边 if(!v[j]&&dis[j]>map[pos][j]) dis[j]=map[pos][j]; //更新到这些点的距离 } if(total>=INF) printf("?\n"); else printf("%d\n",total); } int main(){ int i,j; while(scanf("%d%d",&n,&m)!=EOF){ if(n==0) break; memset(map,INF,sizeof(map)); for(i=1;i<=m;i++) map[i][i]=0; int a,b,c; for(i=1;i<=n;i++){ scanf("%d%d%d",&a,&b,&c); if(c<map[a][b]) //判断是否重边,若重边则保留短的 map[a][b]=map[b][a]=c; } prim(); } return 0; }
相关文章推荐
- sqlite3相关insert操作思路
- CSDN-markdown编辑器使用说明
- Webdriver API (二)
- 密码验证合格程序
- 学习笔记之ArcGIS Engine调用自定义GP服务(亲测!!!)(一)
- android activity状态保存
- linux文件系统管理
- 正方形图片变圆形css
- 配置hadoop集群的lzo压缩
- Android log
- 函数 Func
- 3.2 电话号码对应的英语单词
- LVM的创建,扩展,收缩,快照
- PEP8 Python 编码规范整理
- 标题栏背景色随背景图片自适应
- 通过javascript获取URL中的参数
- myeclipse导出doc
- [HDU 3966] Aragorn's Story 树链剖分
- 单点CAS搭建服务端+客户端
- 运用面向对象原则,设计一款音乐点唱机