您的位置:首页 > 其它

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

2014-05-06 20:20 489 查看
题意:

给出一个图,然后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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MST water kruskal