(专题)最小生成树
来源:互联网 发布:淘宝开店买衣服 编辑:程序博客网 时间:2024/06/06 07:21
最小生成树:kruskal和prim
kruskal:
首先对所有边按权值进行排序,依次选一条短的边,如果加入这条边且不能构成环,就把他加入到最小树里,怎么判断能不能构成环呢,可以把已经连通好了的点归为同一个集合里,每次加边的时候看这两点是否在一个集合里,不在一个集合里则这条边可加,因此可以用并查集来实现,时间复杂度为:(n个点,m条边,O(MlogM+MlogN),因为M一般比N大,所以为O(MlogM);
prim
首先任取一点入树。用一个数组来记录已生成的树到那些未加入树的顶点的距离,每次通过这个数组找离树最近的点,把这个点入树,然后通过这个点松弛其他为入树的点到新树的距离,在找最近点,在松弛,一直到把所有点都入树即可。借助堆优化,可以将复杂度降低到O(MlogN),下面分享一个自己写的裸的优先队列优化的prim
#include<stdio.h>#include<vector>#include<queue>#include<algorithm>#include<string.h>using namespace std;int prim();int build();struct node{int ri,qu;bool operator<(const node &a)const{return qu>a.qu;}};vector<node>w[1000];int n,m,book[1000];priority_queue<node>q;int main(){int a,b,c;while(~scanf("%d %d",&n,&m)){for(int i=0;i<=n;i++)w[i].clear();while(!q.empty()){q.pop();}memset(book,0,sizeof(book));for(int i=0;i<m;i++){scanf("%d %d %d",&a,&b,&c);node t;t.qu=c;t.ri=b;w[a].push_back(t);t.ri=a;w[b].push_back(t);}printf("%d\n",prim());}}int build(){node t;book[1]=1;for(int i=0;i<w[1].size();i++){t=w[1].at(i);q.push(t);}return 0;}int prim(){int ans=1,sum=0;build();node re,pe;while(!q.empty()&&ans<n){re=q.top();q.pop();if(book[re.ri])continue;sum+=re.qu;ans++;book[re.ri]=1;for(int i=0;i<w[re.ri].size();i++){pe=w[re.ri].at(i);if(book[pe.ri])continue;q.push(pe);//printf("ha%d\n",pe.qu);}//printf("%d %d %d %d\n",re.ri,sum,ans,q.empty());}return sum;}
注意理解prim和dijikstra的区别:prim每次找离已生成的树集合最近的点,后者是找离原点最近的点,所以用数组dis来记录生成树到各个顶点的距离,也就是我们要记录的这个距离,并非为这个点到原点的最短距离,而是到任意一个已经入树的树顶点的最短距离。
Description
Your task is to help the Borg (yes, really) by developing a program which helps the Borg to estimate the minimal cost of scanning a maze for the assimilation of aliens hiding in the maze, by moving in north, west, east, and south steps. The tricky thing is that the beginning of the search is conducted by a large group of over 100 individuals. Whenever an alien is assimilated, or at the beginning of the search, the group may split in two or more groups (but their consciousness is still collective.). The cost of searching a maze is definied as the total distance covered by all the groups involved in the search together. That is, if the original group walks five steps, then splits into two groups each walking three steps, the total distance is 11=5+3+3.
Input
Output
Sample Input
26 5##### #A#A### # A##S ####### 7 7##### #AAA#### A## S #### ##AAA########
Sample Output
811
Source
仔细想想其实就是最小生成树的题,只不过刚开始不确定每个点之间的权值;
两个思路,都要用bfs,第一个是先bfs找到每个点之间的权值,然后在最小生成树
第二种是prim,每次用bfs来找理他最近的那个点
#include<stdio.h>#include<queue>#include<string.h>using namespace std;int book[200][200],n,m,tree[200][200];char map[200][200];int go[4][2]={1,0,-1,0,0,1,0,-1};struct node{int x,y,step;}pe,re;int check(node tt){if(tt.x<0||tt.x>=n||tt.y<0||tt.y>=m||book[tt.x][tt.y]||map[tt.x][tt.y]=='#')return 1;return 0;}node bfs(node px){queue<node>q;while(!q.empty()){q.pop();}memset(book,0,sizeof(book));book[px.x][px.y]=1;pe=px;q.push(pe);while(!q.empty()){pe=q.front();q.pop();for(int i=0;i<4;i++){re=pe;re.x+=go[i][0];re.y+=go[i][1];re.step++;if(check(re))continue;if(map[re.x][re.y]=='A'){return re;}q.push(re);book[re.x][re.y]=1;}}}int main(){int i,j,K,k,num,bookk[500];long long int sum;char c;node t,index[500],min,minn[500];scanf("%d",&K);while(K--){memset(tree,0,sizeof(tree));memset(bookk,0,sizeof(bookk));sum=0;k=0,num=0;scanf("%d %d",&m,&n);getchar();//while(c!='\n'){//c=getchar();//}for(i=0;i<n;i++){gets(map[i]);}for(i=0;i<n;i++){for(j=0;j<m;j++){if(map[i][j]=='S'||map[i][j]=='A'){if(map[i][j]=='S')map[i][j]='A';index[k].x=i;index[k].y=j;index[k].step=0;tree[i][j]=k;k++;}}}num=k;for(i=0;i<num;i++)minn[i]=index[i];for(i=0;i<num;i++){if(i==0){//tree[k++]=index[i];bookk[i]=1;map[index[i].x][index[i].y]=' ';}else{min.step=2501;for(j=0;j<num;j++){if(bookk[j]==0)continue;if(map[minn[j].x][minn[j].y]!='A'){minn[j]=bfs(index[j]);}if(minn[j].step<min.step)min=minn[j];}//tree[k]=min;//tree[k++].step=0;bookk[tree[min.x][min.y]]=1;sum+=min.step;map[min.x][min.y]=' ';//printf("%d %d %d\n",min.x,min.y,min.step);}}printf("%lld\n",sum);}return 0;}
Description
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
Output
Sample Input
23 31 2 12 3 23 1 34 41 2 22 3 23 4 24 1 2
Sample Output
3Not Unique!
Source
当时还不知道次小生成树,理解题意后,想着是应该先生成一颗最小树,把树上的边记录下来,暴力每次不用已知生成树里的一条边,然后在生成一颗最小树,看和已知最小树大小一不一样;
做完听某k君说还有更高效的方法,
下面是我的比较笨的方法:
#include<stdio.h>#include<vector>#include<algorithm>#include<string.h>using namespace std;int f[200],ans,sum,sum1;struct node{int le,ri,cost;};void init(int n){ans=0;sum1=0;for(int i=0;i<=n;i++)f[i]=i;return;}int find(int x){if(x==f[x])return x;return f[x]=find(f[x]);}int merge(int a,int b){int t1,t2;t1=find(a);t2=find(b);if(t1!=t2){f[t1]=t2;return 1;}return 0;}int cmp(node a,node b){return a.cost<b.cost;}int main(){int n,m,i,map[200][200],j,k,flog;node t;node index[200]; vector<node>q;scanf("%d",&k);while(k--){memset(map,0,sizeof(map));scanf("%d %d",&n,&m);flog=0;sum=0;init(n);q.clear();for(i=0;i<m;i++){scanf("%d %d %d",&t.le,&t.ri,&t.cost);q.push_back(t);}sort(q.begin(),q.end(),cmp);for(i=0;i<q.size();i++){t=q.at(i);if(merge(t.le,t.ri)){sum+=t.cost;index[ans++]=t;//map[t.le][t.ri]=map[t.ri][t.le]=t.cost;}if(ans==n-1)break;}for(j=0;j<n-1;j++){init(n);for(i=0;i<q.size();i++){t=q.at(i);if(index[j].le==t.le&&index[j].ri==t.ri||index[j].le==t.ri&&index[j].ri==t.le){continue;}if(merge(t.le,t.ri)){ans++;sum1+=t.cost;}if(ans==n-1)break;}if(sum1==sum){flog=1;break;}}if(flog){printf("Not Unique!\n");}else{printf("%d\n",sum);}}return 0;}
k度限制生成树:待补~~~!!!
- (专题)最小生成树
- 最小生成树专题
- 最小生成树专题
- 最小生成树专题
- 最小生成树专题
- 专题六-最小生成树
- UVa10034/POJ2560_Freckles(最小生成树)(小白书图论专题)
- Kuangbin Flying 6最小生成树专题
- 【各大OJ】最小生成树专题
- 【最小生成树入门专题1】G
- 【最小生成树入门专题1】A
- 【最小生成树入门专题1】C
- 【最小生成树入门专题1】H
- [kuangbin带你飞]专题六 最小生成树 (prim)(kruskal)(模板)
- HDU 1233 还是畅通工程 (kuangbin带你飞 专题六 最小生成树)
- hdu 1875 畅通工程再续(kuangbin带你飞 专题六:最小生成树)
- POJ 1287 Networking (kuangbin带你飞 专题六:最小生成树)
- POJ 2421 HDOJ 1102 Constructing Roads(kuangbin带你飞 专题六:最小生成树)
- centos 7 yum 安装LAMP服务器 Apache PHP MariaDB
- 如何描述事物(对象)
- 【博弈】hdu1850 && hdu2176 (尼姆博弈)
- 使用Node.js实现一个简单的ZooKeeper客户端
- 第七届蓝桥杯B组 第二题 生日蜡烛
- (专题)最小生成树
- tar.gz和gz
- 学习笔记---C语言中的数据存储原理
- Linux常用命令-网络命令
- Unity-tweak-tool插件
- Android SurfaceView中的Surface,openGL es中 EGLDisplay,EGLConfig,EGLContext,EGLSurface
- 我的研究生生活
- mongodb增加/删除字段
- ArcGIS卸载较新版本后无法安装较旧版本