题目大意:
找出从起点到终点路径最小边的最大值
这题有一个陷阱,假设最大值为max,则每次运输的人数只能为max-1,因为每次导游要包含在运输人数里
思路:
贪心+最大生成树kruskal算法
每次找最大的一条边,如果这条边连接了两棵不同的树,则合并这两棵树,直到起点与终点联通,则当前边的值即为最小边的最大值
kruskal算法代码如下:(AC)
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define MAXIN 10009
struct edge {
int u, v, w;
}e[MAXIN];
int N, R, S, D, T;
int f[110];
bool cmp(const edge& e1, const edge& e2)
{
return e1.w > e2.w;
}
int father(int n)
{
return n == f[n] ? n : f[n] = father(f[n]);
}
int Kruskal()
{
for (int i = 1; i <= N; i++)
f[i] = i;
sort(e, e + R, cmp);
for (int i = 0; i < R; i++)
{
int l, r;
l = father(e[i].u);
r = father(e[i].v);
if (l != r)
{
f[l] = r;
if (father(S) == father(D))
return e[i].w;
}
}
return 0;
}
int main()
{
int cas = 0;
for (;;)
{
cin >> N >> R;
if (!N && !R)return 0;
cas++;
for (int i = 0; i < R; i++)
{
cin >> e[i].u >> e[i].v >> e[i].w;
}
cin >> S >> D >> T;
int cap = Kruskal() - 1;
int ans = 0, total = 0;
while (ans < T)
{
ans += cap;
total++;
}
cout << "Scenario #" << cas << endl;
cout << "Minimum Number of Trips = " << total << endl<<endl;
}
}
kruskal算法的核心步骤:
每个点为一颗单独的树 f[i]=i
边排序
由大到小处理每一条边
很容易犯的一个错误就是f[n]的使用与father(n)使用的混淆,一定要想清楚什么时候是f[n],什么时候是father[n]
其实我一开始不是这么想的。
开始我的想法是求出每一条路径,记录路径上的最小边,取最小边中最大的那一个。
那么怎么历遍每一条路径呢?我用的是DFS算法,可是提交时产生了运行超时的错误。
毕竟如果深度太深DFS速度就会比较慢。
这个代码写的时候要特别注意,每次DFS递归完时,要把当前点的visit重新置为0,否则可能不会历遍每一条路径。
代码如下:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int G[100][100],visit[100];
int N, R,S, D, T,cap;
int cas = 0;
void DFS(int s,int d,int m)
{
if (s == d)
{
cap = cap > m ? cap : m;
return;
}
visit[s] = 1;
for(int i=1;i<=N;i++)
if (G[s][i]&&!visit[i])
{
if (G[s][i] < m)
DFS(i, d, G[s][i]);
else
DFS(i, d, m);
}
visit[s] = 0;
}
void Init()
{
memset(G, 0, sizeof(G));
memset(visit, 0, sizeof(visit));
for (int i = 0; i < R; i++)
{
int x, y,z;
cin >> x >> y >> z;
G[y][x] = G[x][y] = z;
}
cin >> S >> D >> T;
cap = -(1 << 20);
}
void solve()
{
int ans = 0; int j = 0;
while (ans < T)
{
ans += (cap-1);
j++;
}
cas++;
cout << "Scenario #" << cas << endl;
cout << "Minimum Number of Trips = " << j << endl;
}
int main()
{
freopen("c:\\data\\10099.txt", "r", stdin);
for (;;)
{
cin >> N >> R;
if (N == 0 && R == 0)return 0;
Init();
DFS(S, D,1<<20);
solve();
}
}