0

这基本上是一个 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

4

0 回答 0