hdu 1598 find the most comfortable road 并查集+贪心

来源:互联网 发布:xmanager for mac下载 编辑:程序博客网 时间:2024/06/06 18:04

http://acm.hdu.edu.cn/showproblem.php?pid=1598

题意:给定有向图和起点和终点,求从起点到终点的路径中,权重最大和最小的边的最小差。

思路:很好的一道题目。一开始看到图的点数最多为200个的时候想到可以用floyd做,但是后来就发现其实最小差并没有最优子问题的性质,也就是说用dis[i][j]表示i和j之间的最小差,在dis[i][j]取到最优的时候,并不一定是dis[i][k] 和 dis[k][j] 取到最优的时候,因此这里我们并不能用floyd。这里我们可以这样考虑,在每次给定一对起点和终点的时候,因为只有1000条边, 我们可以考虑依次枚举最小的权重, 然后每次添加一条边, 直到起点和终点连通为止,此时由最大边就可以得出一个差值,这样一次枚举所有的可能就可以得出最终的最优解。这里判断图是否连通可以用并查集的方法。

代码: 

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int INF = 0x3f3f3f3f ;int N , M ,Q;struct Node{int s,e,d ;}edge[1010] ;bool comp(Node n1, Node n2){return n1.d < n2.d;}int f[210] ;void Init(){for(int i=1;i<=N;i++)f[i] = i ;}int find(int a){if(a != f[a]){f[a] = find( f[a] ) ;}return f[a] ;}void Union(int a, int b){int fa = find(a) ;int fb = find(b) ;if(fa == fb)return ;if(fa < fb){f[fb] = fa ;}elsef[fa] = fb;}int main(){int a, b,c ;while(scanf("%d %d",&N,&M) == 2){for(int i=0;i<M;i++){scanf("%d %d %d",&a,&b,&c);edge[i].s = a  ;edge[i].e = b ;edge[i].d = c ;}sort(edge,edge+M,comp);scanf("%d",&Q);for(int i=1;i<=Q;i++){int u ,v ;int ans = INF ;scanf("%d %d",&u,&v);for(int j=0;j<M;j++){Init() ;int minlen = edge[j].d ,maxlen;for(int k=j;k<M;k++){a = edge[k].s ;b = edge[k].e ;c = edge[k].d ;Union(a,b) ;if(find(u) == find(v)){maxlen = edge[k].d ;if(ans > maxlen - minlen){ans = maxlen - minlen;}break ;}}}if(ans == INF)ans = -1 ;printf("%d\n",ans);}}return 0 ;}