XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的“舒适度”有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ),
但XX星人对时间却没那么多要求。要你找出一条城市间的最舒适的路径。(SARS是双向的)。
但XX星人对时间却没那么多要求。要你找出一条城市间的最舒适的路径。(SARS是双向的)。
第一行有2个正整数n (1<n<=200)和m (m<=1000),表示有N个城市和M条SARS。
接下来的行是三个正整数StartCity,EndCity,speed,表示从表面上看StartCity到EndCity,限速为speedSARS。speed<=1000000
然后是一个正整数Q(Q<11),表示寻路的个数。
接下来Q行每行有2个正整数Start,End, 表示寻路的起终点。
4 4 1 2 2 2 3 4 1 4 1 3 4 2 2 1 3 1 2
10
题意:
找出一个最小生成树,其各个连通的节点之间边长与下一个边长的的差值相对最小,且满足题中所给的点连通。求出这个最小生成树的边的的最大值与最小值的差。
题解:
将各条边按从小到大排序,依次选取最小边,最多有m条,从当前最小边开始依次选取比它大的边添加到生成树中。每加入一条边就判断依次题中所给的两点是否连通,如果连通,求出当前最小边与当前最大边的差值。取所有差值的最小值。
因为所有的边都是按照从小到大排列,所以最大值与最小值的差最小的最小生成树,各条边的差值相对最小。即贪心思维。
代码如下:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f struct node { int x,y,s; } q[11000]; int n,m; int f[3100]; int cmp(node a,node b) { return a.s<b.s; } void fun()//初始化父结点 { for(int i=1; i<=n; i++) f[i]=i; } int getf(int x)//寻找父节点,擒贼先擒王原则 { if(f[x]==x) return x; else { //路径压缩,每次返回时,顺便把遇到的点的父节点改为找到的父结点 //提高寻找速度 f[x]=getf(f[x]); return f[x]; } } void merg(int xx,int yy)//合并两个子集 { int t1=getf(xx);//寻找自己的父结点 int t2=getf(yy); if(t1!=t2)//靠左原则,左边的值变为右边的父节点 f[t2]=t1; } int main() { while(~scanf("%d%d",&n,&m)) { int i,j,a,b,k,t; for(i=0; i<m; i++) scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].s); sort(q,q+m,cmp); scanf("%d",&t); for(i=0; i<t; i++) { scanf("%d%d",&a,&b); int minn=INF; for(j=0; j<m; j++) { fun(); for(k=j; k<m; k++) { merg(q[k].x,q[k].y); //此处不能用f[a]==f[b],因为有的节点的父节点未更新 //而调用getf函数可找到其父节点 if(getf(a)==getf(b)) { int r=q[k].s-q[j].s; minn=min(minn,r); break; } } } //如果minn的值未改变则说明这两点无法连通 if(minn==INF) printf("-1\n"); else printf("%d\n",minn); } } return 0; }