这基本上是一个 ICPC 东京区域问题 - Slim Span(UVA -1395)
链接到问题 - https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4141
该问题指出,最苗条的树是其最短边和最长边之间差异最小的树,并且树本身不需要是最小生成树,它只需要是生成树即可。
#include <iostream>
#include <vector>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <utility>
#include <algorithm>
#include <set>
using namespace std;
const int MAX = 110;
struct ii{
int first,second,third;
ii(int x, int y, int z){
first=x;//destination node
second=y;//weight of the edge
third=z;//slimness
}
bool operator<(const ii& rhs) const
{
return third > rhs.third;//slimmest edge first
}
};
vector <ii> adj[MAX];//adjacency list
int prim(int source, int n){
int maximum=-1, minimum=987654321;//maximum and minimum edge lengths
set<int> notvisited;//nodes not yet visited by prim
priority_queue< ii, vector< ii > > pq;
for(int i=1;i<=n; ++i){
notvisited.insert(i);
}
pq.push(ii(source, 0,0));
set<int>::iterator iterator1;
while(!pq.empty() && !notvisited.empty()){
ii temp=pq.top();
pq.pop();
int s=temp.first;//target
int w=temp.second;//weight of edge
//if visited->continue
if((iterator1=notvisited.find(s))==notvisited.end())continue;
notvisited.erase(s);
if(w!=0){
maximum=max(maximum,w);
minimum=min(minimum,w);
}
for(int i=0; i<adj[source].size(); ++i){
int target=adj[source][i].first;
int targetw=adj[source][i].second;
int slimness=targetw-w;
if((iterator1=notvisited.find(target))!=notvisited.end()){
pq.push(ii(target,targetw,max(slimness, 0-slimness)));
}
}
}
return maximum-minimum;
}
我的想法是使用苗条而不是权重对边缘进行排序。它不起作用,因为从一开始它总是将最短边标记为已访问。
如何更正我的程序以解决此问题?
样本输入-
4 6//节点数,边数
1 2 10//源目标权重
1 3 100
1 4 90
2 3 20
2 4 80
3 4 40
输出 - 20