poj3532求生成树中最大权与最小权只差最小的生成树+hoj1598俩个点之间的最大权与最小权只差最小的路经。
来源:互联网 发布:伴生活智能门禁 知乎 编辑:程序博客网 时间:2024/06/15 10:24
该题是最小生成树问题变通活用,表示自己开始没有想到该算法:先将所有边按权重排序,然后枚举最小边,求最小生成树(一个简单图的最小生成树的最大权是所有生成树中最大权最小的,这个容易理解,所以每次取最小边,求一次最小生成树,这样差值都次这次最小的),记录更新即可。并查集来判断连通。
类似一提,hoj1598,开始时用DFS搜索,TLE,受启发,用枚举方法差不多,只是在每次枚举最小边的时候结束条件改为起点与终点连通,连通就结束(father(start)==father(end))。
#include<iostream> //poj 3532 219MS#include<cstring> //最小生成树有一个很重要的性质:在构造生成树时有可能选择不同的边,但最小生成树的权是唯一的!所以在用kruskal算法时第一次加入的必然是最小生成树的最小边权值,最小边确定后,最小生成树的最大边的权值是所以生成树中最小的,于是只要枚举最小边,然后求最小生成树,就可以得到最大边,只要每次更新最优解就行了。#include<cstdio>#include<vector>#include<algorithm>using namespace std;struct edge //边{ int pre; //前一个点//一边的俩端点 int to; //后一个点 int w;};int best;int curmin,curmax;int fa[202];int flag=0;bool my(const edge &a,const edge & b ){ return a.w<b.w;}int father(int x){ return (x==fa[x]?x:father(fa[x]));}int main(){ int n,m; while(~scanf("%d%d",&n,&m)&&(m+n)) { vector<edge>v(m); int s,l,w; for(int i=0;i<m;i++) { scanf("%d%d%d",&s,&l,&w); v[i].to=l; v[i].w=w; v[i].pre=s; } sort(v.begin(),v.end(),my); //排序 best=1000001;flag=0; for(int i=0;i<m;i++) //按从小到大枚举边 { for(int ii=0;ii<=n;ii++) //初始化并查集 fa[ii]=ii; int num=0; curmin=v[i].w; curmax=-1; for(int k=i;k<m;k++) //并查集判断联通 { int xx=father(v[k].pre); int yy=father(v[k].to); if(xx!=yy) //连通性判断 { if(curmax<v[k].w) curmax=v[k].w; if(curmax-curmin>best)break; //无此剪枝3000MS。 fa[xx]=yy; num++; } } if(i==0&&num!=n-1){flag=1;break;} if(num==n-1&&best>curmax-curmin) best=curmax-curmin; } if(flag||m==0){printf("-1\n");continue;} else printf("%d\n",best); } return 0;}
#include<iostream> //100+MS #include<cstring> //最小生成树有一个很重要的性质:在构造生成树时有可能选择不同的边,但最小生成树的权是唯一的!所以在用kruskal算法时第一次加入的必然是最小生成树的最小边权值,最小边确定后,最小生成树的最大边的权值是所以生成树中最小的,于是只要枚举最小边,然后求最小生成树,就可以得到最大边,只要每次更新最优解就行了。#include<cstdio>#include<vector>#include<algorithm>using namespace std;struct edge //边{ int pre; //前一个点//一边的俩个端点 int to; //后一个点 int w;};int best;int curmin,curmax;int fa[202];int flag=0;bool my(const edge &a,const edge & b ){ return a.w<b.w;}int father(int x){ return (x==fa[x]?x:father(fa[x]));}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { vector<edge>v(m); int s,l,w; for(int i=0;i<m;i++) { scanf("%d%d%d",&s,&l,&w); v[i].to=l; v[i].w=w; v[i].pre=s; } sort(v.begin(),v.end(),my); //排序 int q;scanf("%d",&q); while(q--) { int start,end; scanf("%d%d",&start,&end); best=1000001; for(int i=0;i<m;i++) //按从小到大枚举边 { flag=0; for(int ii=0;ii<=n;ii++) //初始化并查集 fa[ii]=ii; curmin=v[i].w; curmax=-1; for(int k=i;k<m;k++) //并查集判断联通 { int xx=father(v[k].pre); int yy=father(v[k].to); if(xx!=yy) //连通性判断 { if(curmax<v[k].w) curmax=v[k].w; if(curmax-curmin>best)break; //无此剪枝300+MS。 fa[xx]=yy; } if(father(start)==father(end)){ flag=1;break;} //联通则退出 } if(flag==0&&i==0){break;} if(flag==1&&best>curmax-curmin) best=curmax-curmin; } if(best==1000001||m==0){printf("-1\n");continue;} else printf("%d\n",best); } } return 0;}
#include<iostream> //搜索TLE#include<cstring>#include<cstdio>#include<vector>using namespace std;struct edge{ int pre; int to; int w;};int head[202];int mark[202];int best;int curmin,curmax;int flag=0;void dfs(int end,vector<edge>v,int cur,int shendu,int n){ if(best==0)return; if(flag)return; if(shendu==n){flag=1;return;} if(curmax-curmin>=0&&curmax-curmin>=best)return; if(cur==end) { if(curmax-curmin<best) best=curmax-curmin; return; } for(int i=head[cur];i!=-1;i=v[i].pre) if(mark[v[i].to]==0) { int tempcurmin=curmin;int tempcurmax=curmax; if(v[i].w<curmin)curmin=v[i].w; if(v[i].w>curmax)curmax=v[i].w; mark[v[i].to]=1; dfs(end,v,v[i].to,shendu+1,n); curmin=tempcurmin; curmax=tempcurmax; mark[v[i].to]=0; } return ;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { vector<edge>v(2*m); int s,l,w; memset(head,-1,sizeof(head)); for(int i=0;i<2*m;i++) { scanf("%d%d%d",&s,&l,&w); v[i].to=l;v[i].w=w; v[i].pre=head[s]; head[s]=i; i++; v[i].to=s;v[i].w=w; v[i].pre=head[l]; head[l]=i; } int q;scanf("%d",&q); int start,end; while(q--) { scanf("%d%d",&start,&end); memset(mark,0,sizeof(mark)); flag=0; best=1000001;curmin=1000001;curmax=-1; mark[start]=1; dfs(end,v,start,1,n); if(best==1000001)printf("-1\n"); else printf("%d\n",best); } } return 0;}
0 0
- poj3532求生成树中最大权与最小权只差最小的生成树+hoj1598俩个点之间的最大权与最小权只差最小的路经。
- hdu1598 求满足最大权值最小权值差最小的生成树
- poj-2485-Highways-最小生成树的最大权边
- poj 3723 最大权森林 最小生成树的运用
- Out of Hay(最小生成树的最大权)
- Prim最小生成树(求,生成树中权值的和,最大权值,最小权值) 参考poj1258 2485
- Frogger【最小生成树的变形】---路径上最小的最大权
- poj2253 最小生成树最大权
- Heavy Transportation(最小生成树的最大权的最短路算法)
- POJ 2485 Highways(最小生成树,树的最大权值边)
- POJ3723 Conscription , 最大权森林问题 ->最小生成树问题
- 最小生成树与最短路的区别
- 图的最小生成树与最短路径
- 最小生成树与最短路径的区别
- 图的遍历与最小生成树
- HDU-2255(记录km算法的板子,km求最大权,最小权匹配)
- HDU1301 最小生成树 + Prim +(Prim求最小生成树与Dijkstra求最短路的区别) (如此题不要误解题意为用Dijkstra!)
- 最小生成树(城市之间的最短距离)
- cocos2dx plist和batchNode总结
- hibernate多对多中间表数据生成详解mappedBy
- linux如何查找文件并打印文件内容
- 常用自动生成语句
- 动态链接库的创建与使用
- poj3532求生成树中最大权与最小权只差最小的生成树+hoj1598俩个点之间的最大权与最小权只差最小的路经。
- CSS入门之列表样式用法及实例,list-style-image,list-style-type
- 针对某undefined对象的属性求值时遇到的错误
- winform窗体加背景图片后,控件闪烁
- SRM 603 D2 L3:GraphWalkWithProbabilities
- 完整的rac带dataguard实验
- Flex mxmlc编译命令选项
- delphi 遍历文件算法(含遍历目录算法)
- 走进新浪微博的真实世界