【最小生成树】图论复习(三)
来源:互联网 发布:股票交易记录数据 编辑:程序博客网 时间:2024/09/21 08:15
最小生成树就两种算法。一种Prim,另一种Kruscal,因为Prim酷似Dijkstra,我又比较喜欢写Dijkstra,所以我还是经常写Prim,当然偶尔也写写Kruscal,感觉效率上要高一点。这里就主要发Kruscal吧。
毕竟处于入门阶段,做的题也不会太难,大牛直接忽略吧。
第一题,按照惯例是裸题。造路行动
Kruscal写的,没什么好说。
代码:
#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int maxn=100+10;struct edge{ int left; int right; int len; bool flag;}edges[maxn];int f[maxn];int n,k;int cmp(const void *a,const void *b){ return (*(edge *)a).len - (*(edge *)b).len;}void init(){ freopen("rqnoj370.in","r",stdin); freopen("rqnoj370.out","w",stdout);}int find(int x){ if(f[x]==x)return x; f[x]=find(f[x]); return f[x];}void merge(int u,int v){ int fu=find(u); int fv=find(v); if(fu!=fv)f[fu]=fv;}void predoing(){ for(int i=1;i<=n;i++) f[i]=i;}void readdata(){ scanf("%d%d",&n,&k); predoing(); for(int i=1;i<=k;i++) { scanf("%d%d%d",&edges[i].left,&edges[i].right,&edges[i].len); }}bool query(int a,int b){ if(find(a)!=find(b))return true; return false; }void solve(){ int ans=0; int haveput=1; int i=1; qsort(&edges[1],k,sizeof(edges[0]),cmp); while(haveput < n) { if(query(edges[i].left,edges[i].right)) { edges[i].flag=true; merge(edges[i].left,edges[i].right); haveput++; } i++; } for(int i=1;i<=k;i++) { if(edges[i].flag==false) { ans+=edges[i].len; } } printf("%d",ans); }int main(){ init(); readdata(); solve(); return 0;}
第三题:联络员
在裸题的基础上变了形,不过也比较简单。如果是必选渠道就在读入的时候先加入生成树,然后再做一次MST,累加出来的ans就是所求了。
代码:
#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;const int maxn = 2000 + 10;const int maxm = 10000 + 10;struct edge { int l,r,w; }edges[maxm];int f[maxn];int n,m;int ans = 0;int haveput = 0;void init(){ freopen("tyvj1307.in","r",stdin); freopen("tyvj1307.out","w",stdout);}int cmp(const void *a,const void *b){ return (*(edge *)a).w - (*(edge *)b).w;}int find(int x){ if(f[x] == x)return x; f[x] = find(f[x]); return f[x];}void predoing(){ for(int i = 1;i <= n;i++) { f[i] = i; }}void merge(int x,int y){ int wx = find(x); int wy = find(y); f[wx] = wy;}void readdata(){ scanf("%d%d",&n,&m); predoing(); for(int i = 1;i <= m;i++) { int x,y,w,l; scanf("%d%d%d%d",&l,&edges[i].l,&edges[i].r,&edges[i].w); if(l == 1) { ans += edges[i].w; if(find(edges[i].l) != find(edges[i].r)) { merge(edges[i].l,edges[i].r); haveput++; } } }}int solve(){ qsort(&edges[1],m,sizeof(edges[0]),cmp); int i = 1; while(haveput < n - 1) { if(find(edges[i].l) != find(edges[i].r)) { ans += edges[i].w; merge(edges[i].l,edges[i].r); ++haveput; } i++; } printf("%d",ans);}int main(){ init(); readdata(); solve(); return 0;}最后一道:mty的宝藏
也属于一道变型,判断一个图中有没有环。因为我们知道在最小生成树中必然是不存在环的,所以我们可以在读入时累加,在求出MST与累加的值比较,如果MST=累加值,那么不存在环,如果MST<累加值,说明图中存在了环,明白了这个代码就好写了,这道题是用Prim做的。
代码:
#include<cstdio>#include<cstring>#include<queue>using namespace std;const int maxn = 1000 + 10;int map[maxn][maxn];int dist[maxn];bool done[maxn];int n,com,sum;void init(){ freopen("rqnoj564.in","r",stdin); freopen("rqnoj564.out","w",stdout);}void readdata(){ memset(done,false,sizeof(done)); memset(dist,67,sizeof(dist)); sum = com = 0; scanf("%d",&n); for(int i = 1;i <= n;i++) for(int j = 1;j <= n;j++) { int p; scanf("%d",&p); if(p) { map[i][j] = 1; sum += 1; } } }void solve(){ com = 0; typedef pair<int,int> pii; priority_queue<pii,vector<pii>,greater<pii> >q; dist[1] = 0; q.push(make_pair(dist[1],1)); for(int i = 1;i <= n;i++) { pii u = q.top(); q.pop(); while(done[u.second]) { u = q.top(); q.pop(); } int k = u.second; done[k] = true; com += dist[k]; for(int j = 1;j <= n;j++) { if(!map[k][j])continue; if(done[j])continue; if(map[k][j] < dist[j]) { dist[j] = map[k][j]; q.push(make_pair(dist[j],j)); } } } if(com == sum) printf("%c",'N'); else printf("%c",'Y');}int main(){ init(); readdata(); solve(); return 0;}
总结:最小生成树以及最短路是图论中的经典问题,NOIP也很可能考到,一定要注意灵活运用,不能太死板,要多多训练自己抽象模型的能力。
(Ps:发这么些水题出来感觉有点。。。不过也算了,人都是会慢慢成长的,大牛在最开始不也是弱菜么?我现在要努力向前!)
- 【最小生成树】图论复习(三)
- 复习最小生成树问题
- 【算法复习】图的最小生成树(Prim&Kruskal)
- 图论学习(三)求最小生成树
- soj 3366 复习最小生成树kruskal
- POJ2421——最小生成树复习
- 最后复习之最小生成树
- [复习]最小生成树 最优布线问题
- 蒟蒻复习之-----最小生成树
- 【复习记录】最小/大生成树
- 图之三(最小生成树)
- 算法复习(一)——最小生成树
- [算法第一轮复习] kruskal求最小生成树算法
- NOIP复习-006——最小生成树
- (复习)图论--最小生成树--Prim算法
- (复习)图论--最小生成树--Kruskal算法
- 图论专项菜鸡入门(三):树的初步入门+最小生成树
- 最小生成树 图
- SQL Server数据库常用的T-SQL命令
- 轻松掌握AJAX异步通信
- Java调用XML的方法:DocumentBuilderFactory
- POJ 1067 取石子游戏 (巴什博弈+威佐夫博弈)
- c/c++将结构体读入到文件中,然后读出
- 【最小生成树】图论复习(三)
- 技术进步提高为什么会造成保存生命危机?
- private,单例,同时可以防止被继承
- 在iOS开发中使用FMDB
- 《大教堂与集市》的读书笔记
- “对象关闭时,不允许操作”的解决
- 取得SIM卡内的信息
- mongodb shell命令大全
- window.getComputedStyle详解