這道題還是求最小生成樹。兩個村莊connected的定義就是一般意義上的connected,只不過是通過「遞迴」地定義的:要不直接有路相連,要不鄰接的村莊能「connect」。這就是最小生成樹的目的:所有點都是聯通的,但是又是最小的。
因而常見的兩種最小生成樹演算法:prim和kruskal都可以用。我這裡用的是kruskal,因為之前的1251,1258都已經用過。直接用的之前的**。
這道題不同之處是規定有些路(無論遠近)已經包含在最小生成樹裡面了。這裡的處理辦法就是把這些路的距離設為0,這樣求最小生成樹的時候必然會先考慮完這些路再(從小到大)考慮別的。
thestoryofsnow
2421
accepted
264k
79ms
c++
/*
id: thestor1
lang: c++
task: poj2421
*/#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;
void makeset(const int n, std::vector&parent, std::vector&rank)
}int find(int u, std::vector&parent)
return parent[u];
}void union_set(int u, int v, std::vector&parent, std::vector&rank)
if (rank[ru] < rank[rv])
else if (rank[rv] < rank[ru])
else }
class edge
edge(int u, int v, int w) : u(u), v(v), w(w) {}
bool operator< (const edge &rhs) const
return this->u < rhs.u || (this->u == rhs.u && this->v < rhs.v);
}};int kruskal(const int n, std::vector&edges)
} return mst;
}int main() }
int q;
scanf("%d", &q);
for (int i = 0; i < q; ++i)
std::vectoredges(n * (n - 1) / 2);
int edgeno = 0;
for (int u = 0; u < n; ++u) }
assert (edgeno == n * (n - 1) / 2);
sort(edges.begin(), edges.end());
printf("%d\n", kruskal(n, edges));
return 0;
}
poj2421 最小生成樹
題目鏈結在這裡 題目大意 有n個村莊,每個村莊之間都有一定的距離,想建幾條路使得村莊之間相互連通,問所需要花費的最小代價是什麼。有的村莊之間是相互連通的 解題思路 相互連通的村莊之間的距離置為0,然後將所有村莊之間的距離放到堆裡,直接最小生成樹莽出來就完事了。如下 include include i...
poj解題報告 1328
不得不說,這題是讓我飽受折磨,畢竟第一次做貪心演算法,而且wa了好多次,幸好有學長的幫助,最終找到了問題所在,是在快排上是問題,double高位不可向int低位轉換,由於一開始強制轉換導致雖然樣例和其他的測試資料過了,但還是wa,現在改完了就對了,附上ac ps 這題通過率是22 真心不簡單 如下 ...
poj解題報告 2586
這題我是用的貪心演算法,其實不用也可以,列舉也能解決,因為情況不多。因為是每連續5個月必有虧損,而一年只有1 5,2 6,3 7,4 8 8 12共8種情況。現在設盈餘為s,虧損為d,可列出以下幾種情況。ssssdssssdss 4ssssddsssddss 3s 2d ssdddssdddss 2...