最小生成树练习2(Kruskal)
两个BUG鸣翠柳,一行代码上西天。。。
hdu4786 Fibonacci Tree(生成树)问能否用白边和黑边构成一棵生成树,并且白边数量是斐波那契数。
题解:分别优先加入白边和黑边,求出生成树能包含白边的最大值和最小值,其间有值为斐波那契数即可。
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int M=1e5+;
- const int N=1e5+;
- struct edge{
- int u,v,w;
- }e[M];
- int f[N];
- int fi[];
- int n,m,ans;
- int cmp(edge a,edge b){
- return a.w<b.w;
- }
- void init(){
- for(int i=;i<=n;++i) f[i]=i;
- }
- int fin(int x){
- if(x!=f[x])f[x]=fin(f[x]);
- return f[x];
- }
- void Kruskal(){
- int u,v,i,cnt=,mi=,ma=,flag=;
- init();
- for(i=;i<m;++i){
- u=e[i].u;
- v=e[i].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- if(e[i].w) mi++;
- if(++cnt==n-){flag=;break;}
- }
- }
- if(!flag){printf("No\n");return;}
- init();
- for(i=m-;i>=;--i){
- u=e[i].u;
- v=e[i].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- if(e[i].w) ma++;
- if(++cnt==n-)break;
- }
- }
- for(i=;i<;++i)
- if(mi<=fi[i]&&fi[i]<=ma){
- printf("Yes\n");return;
- }
- printf("No\n");
- }
- int main(){
- int t,i,a,b,c,k=;
- fi[]=;fi[]=;
- for(i=;i<;++i)
- fi[i]=fi[i-]+fi[i-];
- //printf(".%d.",fi[19]);
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&n,&m);
- for(i=;i<m;++i){
- scanf("%d%d%d",&a,&b,&c);
- e[i]={a,b,c};
- }
- sort(e,e+m,cmp);
- printf("Case #%d: ",k++);
- Kruskal();
- }
- return ;
- }
hdu5253 连接的管道(最小生成树)一开始我因为没建好图纠结了ToT~
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const int N=;
- struct edge{
- int u,v,w;
- }e[N*N*];
- int f[N*N];
- int g[N][N];
- int ei,n,m,ans;
- int cmp(edge a,edge b){
- return a.w<b.w;
- }
- int fin(int x){
- if(x!=f[x])f[x]=fin(f[x]);
- return f[x];
- }
- void Kruskal(){
- int u,v,i,cnt=;
- for(ans=i=;i<ei;++i){
- u=e[i].u;
- v=e[i].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- ans+=e[i].w;
- if(++cnt==n*m-)break;
- }
- }
- }
- int main(){
- int t,i,j,h,k=;
- scanf("%d",&t);
- while(t--){
- ei=;
- scanf("%d%d",&n,&m);
- for(i=;i<n;++i){
- for(j=;j<m;++j){
- scanf("%d",&g[i][j]);
- f[i*m+j]=i*m+j;
- if(i>){
- e[ei].u=i*m+j; e[ei].v=(i-)*m+j;
- e[ei++].w=abs(g[i][j]-g[i-][j]);
- }
- if(j>){
- e[ei].u=i*m+j; e[ei].v=i*m+j-;
- e[ei++].w=abs(g[i][j]-g[i][j-]);
- }
- }
- }
- sort(e,e+ei,cmp);
- Kruskal();
- printf("Case #%d:\n%d\n",k++,ans);
- }
- return ;
- }
hdu1598 find the most comfortable road(最小生成树,枚举)第一眼看过去差点想最短路[吓],,这是最小差不是最短路哦。用Kruskal要对边排序,贪心正好哩。枚举最小道路建树,起点和终点连上了就记录最大边与最小边之差,最后选所有情况的最小值就行啦。
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const int inf=0x3f3f3f3f;
- const int M=;
- struct edge{
- int u,v,w;
- }e[M];
- int f[];
- int n,m,ans,st,ed;
- int cmp(edge a,edge b){
- return a.w<b.w;
- }
- void init(){
- for(int i=;i<=n;++i)
- f[i]=i;
- }
- int fin(int x){
- if(x!=f[x])f[x]=fin(f[x]);
- return f[x];
- }
- void Kruskal(){
- int u,v,i,j;
- ans=inf;
- for(i=;i<m;++i){//枚举
- init();
- for(j=i;j<m&&e[j].w-e[i].w<ans;++j){
- u=e[j].u;
- v=e[j].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- }
- if(fin(st)==fin(ed)){
- ans=min(ans,e[j].w-e[i].w);
- break;
- }
- }
- }
- }
- int main(){
- int i,j,q;
- while(scanf("%d%d",&n,&m)==){
- for(i=;i<m;++i)
- scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
- sort(e,e+m,cmp);
- scanf("%d",&q);
- while(q--){
- scanf("%d%d",&st,&ed);
- Kruskal();
- printf("%d\n",(ans==inf)?-:ans);
- }
- }
- return ;
- }
poj3522 Slim Span(最小生成树,枚举)求最大边与最小边之差最小的生成树。和上面那题挺像的,相比之下,这题就是完整的最小生成树了。
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const int inf=0x3f3f3f3f;
- const int N=;
- struct edge{
- int u,v,w;
- }e[];
- int f[N];
- int n,m,ans,st,ed;
- int cmp(edge a,edge b){
- return a.w<b.w;
- }
- void init(){
- for(int i=;i<=n;++i)
- f[i]=i;
- }
- int fin(int x){
- if(x!=f[x])f[x]=fin(f[x]);
- return f[x];
- }
- void Kruskal(){
- int u,v,i,j,cnt;
- ans=inf;
- for(i=;i<m;++i){
- init(); cnt=;
- for(j=i;j<m&&e[j].w-e[i].w<ans;++j){
- u=e[j].u;
- v=e[j].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- if(++cnt==n-){
- ans=min(ans,e[j].w-e[i].w);
- break;
- }
- }
- }
- }
- }
- int main(){
- int i,j,q;
- while(scanf("%d%d",&n,&m),n||m){
- for(i=;i<m;++i)
- scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
- sort(e,e+m,cmp);
- Kruskal();
- printf("%d\n",(ans==inf)?-:ans);
- }
- return ;
- }
poj2784 Buy or Build(最小生成树,二进制枚举)英语渣在艰难地读题orz。已知n个城市的坐标,q个连通块各自的费用,新建一条边的费用为两点距离的平方。求最小生成树。学了一下二进制枚举法。
- #include<cstdio>
- #include<algorithm>
- #include<vector>
- using namespace std;
- const int N=;
- struct edge{
- int u,v,w;
- }e[];
- struct node{
- int x,y;
- }V[N];
- int f[N];
- int a[];
- int n,m,q;
- vector<int>g[];
- int cmp(edge a,edge b){
- return a.w<b.w;
- }
- int dist(int i,int j){
- return (V[i].x-V[j].x)*(V[i].x-V[j].x)+(V[i].y-V[j].y)*(V[i].y-V[j].y);
- }
- void init(){
- for(int i=;i<=n;++i)
- f[i]=i;
- }
- int fin(int x){
- if(x!=f[x])f[x]=fin(f[x]);
- return f[x];
- }
- void uni(int x,int y){
- if((x=fin(x))==(y=fin(y)))return;
- f[x]=y;
- }
- int Kruskal(){
- int u,v,i,j,cnt=,ans=;
- for(i=;i<m;++i){
- u=e[i].u;
- v=e[i].v;
- if((u=fin(u))!=(v=fin(v))){
- f[u]=v;
- ans+=e[i].w;
- if(++cnt==n-)break;
- }
- }
- //printf("%d..\n",ans);
- return ans;
- }
- void solve(){
- int i,j,k,cost,ans;
- init();
- ans=Kruskal();
- for(i=;i<(<<q);++i){//枚举方案
- cost=;
- init();
- for(j=;j<q;++j){
- if(!((i>>j)&))continue;//二进制枚举
- cost+=a[j];
- //printf("COST:%d..",cost);
- for(k=;k<g[j].size();++k)
- uni(g[j][k],g[j][]);
- }
- ans=min(ans,cost+Kruskal());
- }
- printf("%d\n",ans);
- }
- int main(){
- int i,j,num,x;
- while(scanf("%d%d",&n,&q)==){
- for(i=;i<q;++i){
- g[i].clear();
- scanf("%d%d",&num,&a[i]);
- for(j=;j<num;++j){
- scanf("%d",&x);
- g[i].push_back(x);
- }
- }
- for(i=;i<=n;++i) scanf("%d%d",&V[i].x,&V[i].y);
- m=;
- for(i=;i<n;++i){
- for(j=i+;j<=n;++j){
- e[m].u=i; e[m].v=j;
- e[m++].w=dist(i,j);
- }
- }
- sort(e,e+m,cmp);
- solve();
- }
- return ;
- }
最小生成树练习2(Kruskal)的更多相关文章
- 最小生成树之Prim Kruskal算法(转)
最小生成树 首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接下来讨论的图均默认为无向图.对于一个有n个点的图,最少需要n-1条边使得这n个点联通,由这n-1条边组成的子图则称为原 ...
- 最小生成树(prim&kruskal)
最近都是图,为了防止几次记不住,先把自己理解的写下来,有问题继续改.先把算法过程记下来: prime算法: 原始的加权连通图——————D被选作起点,选与之相连的权值 ...
- 图的最小生成树(Prim、Kruskal)
理论: Prim: 基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合.算法从U={u0}(u0∈V).TE={}开始.重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E ...
- 最小生成树模板【kruskal & prim】
CDOJ 1966 Kruskal 解法 时间复杂度O(mlogm) m为边数,这里主要是边排序占时间,后面并查集还好 #include <cstdio> #include <cst ...
- 图-最小生成树算法之Kruskal及其Java实现
1.Kruskal算法 Kruskal算法基于贪心,因此它追求的是近似最优解,也就是说由Kruskal得出的生成树并不一定是最优解. Kruskal算法求最小生成树的关键在于,每次选取图中权值最小(及 ...
- 最小生成树(II)与Kruskal算法
为防止网页加载过慢,故分两章.上接https://www.cnblogs.com/Uninstalllingyi/p/10479470.html Kruskal算法——将森林合并成树 玩过瘟疫公司吗… ...
- 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程
最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...
- poj1861 最小生成树 prim & kruskal
// poj1861 最小生成树 prim & kruskal // // 一个水题,为的仅仅是回味一下模板.日后好有个照顾不是 #include <cstdio> #includ ...
- 最小生成树 Prim算法 Kruskal算法实现
最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...
- 最小生成树求法 Prim + Kruskal
prim算法的思路 和dijkstra是一样的 每次选取一个最近的点 然后去向新的节点扩张 注意这里的扩张 不再是 以前求最短路时候的到新的节点的最短距离 而是因为要生成一棵树 所以是要连一根最短的连 ...
随机推荐
- c#扩展方法的理解(二:接口)
namespace ExtensionInterfaceMethod { class Program { static void Main(string[] args) { //使用接口变量来调用扩展 ...
- linux系统:rm-rf执行以后,怎么办?我来教你恢复文件。
记得我当时也犯过这个错误 rm -rf /* 傻傻的盯着屏幕看... 还好当时是在自己的虚拟机里,没什么数据,打镜像恢复回来就好了.今天看到这篇文章,备用!嗯 是的 万一哪天脑抽了 --------- ...
- ABAP基本数据类型、通用类型
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- zoj 1199 几何公式推导
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=199 Point of Intersection Time Limit: ...
- 《Linux内核设计的艺术》学习笔记(一)从开机加电到加载三个汇编源码
实验内核版本:0.11 ◆ 从开机到main函数的三步: ① 启动BIOS,准备实模式下的中断向量表和中断服务程序: ② 从启动盘加载OS程序到内存中,加载OS程序的工作就是利用第一步中的中断服务 ...
- Typescript的面向对象
封装: var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.prot ...
- FLASH CC 2015 CANVAS (四)制作响应式设计(自适应)的项目
注意 此贴 为个人边“开荒”边写,所以不保证就是最佳做法,也难免有错误(如果发现我会更新文章)! 正式教程会在后续开始更新 相信你在看了(第二节)(第三节)之后已经能够满足绝大多数的互动需求了.那么也 ...
- chubu
python解释型语言,不需要编译成机器认可的二进制码,而是直接从源代码运行程序. python是基于c语言开发的. python很容易嵌入到其他语言. 中文注释,必须在前边加上注释说明 : #_*_ ...
- 记CVTE2014年春季招聘实习生求职历程
进度:目前已经过了网测 明天一面,好紧张,人生第一次实习面试.据说只有一分钟. 网测; 首先在http://exam.cvte.com/ 注册了账号,然后填写相关的个人信息,这里要仔细填写,因为它最后 ...
- iOS - UIActivityViewController
前言 NS_CLASS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED @interface UIActivityViewController : UIViewControl ...