HDU-1598-find the most comfortable road(暴力枚举+Kruskal最小生成树)

题意:

给出一个图,然后Q个询问,每次询问从一个节点到另一个节点,联通图中的“最大边和最小边之差”的最小值,但如果节点之间不连通,则输出-1.

思路:由于询问Q < 11,m < 1000,所以O(Q*n^2),Q*n^2 < 10^8,用最小生成树的思路,在给图上的边排好序的基础上,每次枚举最小边,然后做并查集枚举最大边,当查询的路径相通的时候,如果差值比上一次枚举最小边的差值小的时候,更新。


AC代码:

//AC
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
using namespace std;
#define maxn 20500
#define INF 9000000
int par[maxn], h[maxn], n, m, q;
struct node{
   int s, t, w;
};
bool cmp(node a, node b){
    return a.w < b.w;
}
vector
       
       
         ve; void init(){ for(int i = 0; i <= n; i++){ par[i] = i; h[i] = 0; } } int Find(int x){ if(par[x] == x) return x; return par[x] = Find(par[x]); } void Union(int a, int b){ a = Find(a); b = Find(b); if(a != b){ if(h[a] > h[b]) par[b] = par[a]; else{ if(h[a] == h[b]) h[b]++; par[a] = par[b]; } } } int query(int a, int b){ int ans = INF, j; for(int i = 0; i < ve.size(); i++){//枚举最小边 init(); for(j = i ; j < ve.size(); j++){ int x = Find(ve[j].s), y = Find(ve[j].t); if(x != y){ Union(x, y); } if(Find(a) == Find(b)) { //找到最大边 if(ans > ve[j].w - ve[i].w) ans = ve[j].w - ve[i].w; break; } } if(j == m) break; //如果j == m则不必继续往下枚举了 } return ans; } void work(){ ve.clear(); init(); for(int i = 0; i < m; i++){ node n; scanf("%d%d%d", &n.s, &n.t, &n.w); ve.push_back(n); } sort(ve.begin(), ve.end(), cmp); scanf("%d", &q); for(int i = 0; i < q; i++){ int a, b, c; scanf("%d%d", &a, &b); c = query(a, b); printf("%d\n", (c == INF) ? -1 : c); } } int main() { while(scanf("%d%d", &n, &m) != EOF){ init(); work(); } return 0; } 
       
      
      
     
     
    
    
   
   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值