题目意思:
有一个旅游团现在去出游玩,现在有n个城市,m条路。由于每一条路上面规定了最多能够通过的人数,现在想问这个旅游团人数已知的情况下最少需要运送几趟
思路:最大生成树 + kruskal
分析:从题目可以知道从起始点到达终点的路径可能会有很多条,但是现在要求运送的次数最少,那么就是要满足每一次的运送都能够达到最多的人数。那么这就转变成求在满足条件的所有路径中所有边最小值中的最大值。那么只要按照求解最小生成树的过程,把排序改成按照大的排序然后在生成树的时候判断目标点是否在同一个连通分支里面,如果在同一个连通分支里面那么ans就是当前这条边的长度。最后求几次的时候在判断一下是否可以整除
注意:由于导游每一次都要跟着车走,那么实际上能够载的人数是要减1的。
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; #define MAXN 110 int n , m; int star , end , goal; int ans , cnt; int father[MAXN]; int rank[MAXN]; struct Edge{ int x; int y; int value; }e[100010]; bool cmp(Edge e1 , Edge e2){ return e1.value > e2.value; } void init_Set(){ for(int i = 1 ; i <= n ; i++){ father[i] = i; rank[i] = 1; } } int find_Set(int x){ int tmp = x; while(father[tmp] != tmp) tmp = father[tmp]; while(father[x] != tmp){ int tmp_x = father[x]; father[x] = tmp; x = tmp_x; } return tmp; } void union_Set(int x , int y){ if(rank[x] >= rank[y]){ rank[x] += rank[y]; father[y] = x; } else{ rank[y] += rank[x]; father[x] = y; } } void kruskal(){ init_Set(); sort(e , e+m , cmp); for(int i = 0 ; i < m ;i++){ int root_x = find_Set(e[i].x); int root_y = find_Set(e[i].y); if(root_x != root_y){ union_Set(root_x , root_y); if(find_Set(star) == find_Set(end)){ ans = e[i].value; break; } } } int num; num = goal/(ans-1); if(goal % ans) num++; printf("Scenario #%d\n" , cnt++); printf("Minimum Number of Trips = %d\n\n" , num); } int main(){ // freopen("input.txt" , "r" , stdin); cnt = 1; while(scanf("%d%d" , &n , &m) && n+m){ for(int i = 0 ; i < m ; i++) scanf("%d%d%d" , &e[i].x , &e[i].y , &e[i].value); scanf("%d%d%d" , &star , &end , &goal); kruskal(); } return 0; }