poj3532求生成树中最大权与最小权只差最小的生成树+hoj1598俩个点之间的最大权与最小权只差最小的路经。
该题是最小生成树问题变通活用,表示自己开始没有想到该算法:先将所有边按权重排序,然后枚举最小边,求最小生成树(一个简单图的最小生成树的最大权是所有生成树中最大权最小的,这个容易理解,所以每次取最小边,求一次最小生成树,这样差值都次这次最小的),记录更新即可。并查集来判断连通。
类似一提,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;
}
poj3532求生成树中最大权与最小权只差最小的生成树+hoj1598俩个点之间的最大权与最小权只差最小的路经。的更多相关文章
- POJ2349(求生成树中符合题意的边)
Arctic Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 14977 Accepted: 4777 D ...
- POJ-2485 Highways---最小生成树中最大边
题目链接: https://vjudge.net/problem/POJ-2485 题目大意: 求最小生成树中的最大边 思路: 是稠密图,用prim更好,但是规模不大,kruskal也可以过 #inc ...
- SSAS中事实表中的数据如果因为一对多或多对多关系复制了多份,在维度上聚合的时候还是只算一份
SSAS事实表中的数据,有时候会因为一对多或多对多关系发生复制变成多份,如下图所示: 图1 我们可以从上面图片中看到,在这个例子中,有三个事实表Fact_People_Money(此表用字段Money ...
- UML中关联(Association)、聚合(Aggregation)和合成(Composition)之间的区别
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 现在,我们需要设计一个项目管理系统,目前我们收集到了如下这些需求: REQ1:一个项目内有多名项目成 ...
- Spring中Bean的命名问题(id和name区别)及ref和idref之间的区别
Spring中Bean的命名 1.每个Bean可以有一个id属性,并可以根据该id在IoC容器中查找该Bean,该id属性值必须在IoC容器中唯一: 2.可以不指定id属性,只指定全限定类名,如: & ...
- OpenFramework中视频或者图片进行中心旋转、平移、放大、缩小、矫正(本例以视频为准,只给出主要代码)
/********** update mesh部分***********/ for(int i=0;i<4;i++) { mesh[i].clear(); //重要,不加的话,移动视频的四个角 ...
- (转)Spring中Bean的命名问题(id和name区别)及ref和idref之间的区别
Spring中Bean的命名 1.每个Bean可以有一个id属性,并可以根据该id在IoC容器中查找该Bean,该id属性值必须在IoC容器中唯一: 2.可以不指定id属性,只指定全限定类名,如: & ...
- hibernate中持久化对象的生命周期(三态:自由态,持久态,游离态 之间的转换)
三态的基本概念: 1, 暂时状态(Transient):也叫自由态,仅仅存在于内存中,而在数据库中没有对应数据.用new创建的对象,它没有持久化,没有处于Session中,处于此状态的对象叫暂时对象 ...
- java之线程(线程的创建方式、java中的Thread类、线程的同步、线程的生命周期、线程之间的通信)
CPU:10核 主频100MHz 1核 主频 3GHz 那么哪一个CPU比较好呢? CPU核不是越多越好吗?并不一定.主频用于衡量GPU处理速度的快慢,举个例子10头牛运送货物快还是1架飞机运 ...
随机推荐
- js中json处理总结之JSON.parse
踩过的坑都将成为路上的风景.队友在cookie中已存以下值: address_info {"address_name":"人民大会堂","...lng ...
- SQL函数 Nullif
函数 Nullif 功能: 如果两个函数都为空字符串则返回null 语法: Nullif(参数1,参数2) 一般该函数与函数coalesc一起使用 例: coalesce ( nullif ( [参数 ...
- PHP memcache扩展安装 for Windows
一.下载并安装memcached服务器端软件 1.下载memcached软件 32位下载地址: memcached-win32-1.4.4-14.zip(直接下载),memcached-win3 ...
- 原创:shell两个整数的比较 思想版
思想是学的 代码创作是自己的 很喜欢前几行的逻辑严谨 #!/bin/bash#判断两个整数的大小read -p "请输入两个整数a b :" a b #或者使用a=$1[ -z & ...
- sqlserver 数据库主外键关联错误
话题引入: 在建立主外键关系时,系统提示表"table2"中的列与现有的主键或UNIQUE约束不匹配 原因: 数据库表中只有一个主键,这个主键可以是多个列共同组成.所以table2 ...
- 手工修改注册表激活windows xp法
手工修改注册表激活windows xp法: 1.安装原版windows xp 2.打开注册表regedit 3.找到主键 Hkey_Local_Machine\Software\Microsoft\W ...
- Java sleep方法的作用(sleep())
sleep() 方法的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行).这个“正在执行的线程”是指 this.currentThread() 返回的线程. 例 1 下面通过一个案例来理解 ...
- process data
# version 1.0def connect_mysql(sql, oper_type="select", data_l=None): conn = pymysql.conne ...
- django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module
pip3 install mysqlclient try again python manage.py makemigrations python manage.py migrate
- MySQL配置索引页的合并阈值
MySQL配置索引页的合并阈值 如果删除行或者通过UPDATE操作缩短行 可以为索引页面配置MERGE_THRESHOLD值. 当delete与update缩短了行长度时,索引页的"page ...