这道题题目就是说给你一个图,然后判断能不能成环,不能成环就输出最长的那一条路。
首先分析问题。怎么判断环?这是图中一个很常见的问题,在无向图中判环我们可以用并查集,在有向图中可以使用tarjan或者拓扑排序。
这个问题是无向图,那么就用并查集就好了,在输入图的过程就可以判断,每当有一条线,我们就找这条线两个端点的父亲,如果父亲一样,那么他们就是构成了环。因为父亲一样说明之前已经两个点用过了并且连在一起(祖先是一样的)那么再连一起,就会构成环。`
int flag = 0;
for (int i = 1; i <= m; i++) {
int a = read(), b = read(), c = read();
int t1 = find_(a), t2 = find_(b);
if (t1 == t2)flag = 1;//成环
else {
pre[t1] = t2;//不是共同祖先则直接连上去
}
add_(a, b, c);
add_(b, a, c);
}
if (flag) {
cout << "YES" << endl;
}
好了环的问题解决了,我们如何解决最长的路?由于他没有环,那么其实就是可以树,为什么是树?一个联通图里面如果你边数大于n-1那么一定就是有环了, 没环则一定是树,那么求树的最长路就只是求一遍树直径就好了。
树直径怎么求?就是先随便找一个点,然后由这个点出发的最远距离的那个点开始,在走一遍,所得到的的距离就是树直径。这样也就是一个两遍bfs的过程。
但是这又要考虑一个点,由于边数我们是无法确定,所以可能有情况就是,他这个图是有很多很多个联通块。我们就要算出每一个联通块(每一颗树)的直径,取一个max就可以了。
下面贴出程序,有问题可以留言提问,我会尽力解答。程序中bfs1和bfs2完全是一样的,只是一个返回的是点,一个是返回那个最长路的权值。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const long long max_ = 100000 + 50;
int head[max_],n,m,pre[max_],xiann = 1,pan[max_],pan2[max_];
inline int read()
{
int s = 0, f = 1;
char ch = getchar();
while (ch<'0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0'&&ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * f;
}
struct k {
int next, to, value;
}xian[(1000000+50)*2];
int find_(int x) {
if (pre[x] == x)return x;
else
{
return pre[x] = find_(pre[x]);
}
}
void add_(int a, int b, int c) {
xian[xiann].next = head[a];
xian[xiann].to = b;
xian[xiann].value = c;
head[a] = xiann;
xiann++;
}
struct kk {
int node, length;
};
int bfs1(int now) {
kk temp; temp.node = now; temp.length = 0;
queue<kk> ans;
ans.push(temp);
int maxchang = -1, dian;
while (!ans.empty()) {
kk tou = ans.front(); ans.pop();
if (pan[tou.node] == 1)continue;
pan[tou.node] = 1;
for (int i = head[tou.node]; i; i = xian[i].next) {
int to = xian[i].to;
if (pan[to] != 1) {
temp.length = tou.length + xian[i].value; temp.node = to;
if (temp.length > maxchang) {
maxchang = temp.length;
dian = to;
}
ans.push(temp);
}
}
}
return dian;
}
int bfs2(int now) {
kk temp; temp.node = now; temp.length = 0;
queue<kk> ans;
ans.push(temp);
int maxchang = -1, dian;
while (!ans.empty()) {
kk tou = ans.front(); ans.pop();
if (pan[tou.node] == 1)continue;
pan[tou.node] = 1;
for (int i = head[tou.node]; i; i = xian[i].next) {
int to = xian[i].to;
if (pan[to] != 1) {
temp.length = tou.length + xian[i].value; temp.node = to;
if (temp.length > maxchang) {
maxchang = temp.length;
dian = to;
}
ans.push(temp);
}
}
}
return maxchang;
}
int main() {
while (cin >> n >> m) {
for (int i = 1; i <= n; i++) {
pre[i] = i;
}
int flag = 0;
for (int i = 1; i <= m; i++) {
int a = read(), b = read(), c = read();
int t1 = find_(a), t2 = find_(b);
if (t1 == t2)flag = 1;
else {
pre[t1] = t2;
}
add_(a, b, c);
add_(b, a, c);
}
if (flag) {
cout << "YES" << endl;
}
else {
int dian1;
int aanss = -1;
for (int i = 1; i <= n; i++) {
if (pan2[find_(i)] == 0) {
dian1 = bfs1(i);
pan2[find_(i)] = 1;
for (int i = 1; i <= n; i++) pan[i] = 0;
int tempp = bfs2(dian1);
if (aanss < tempp)aanss = tempp;
}
}
cout << aanss << endl;
}
xiann = 1;
for (int i = 1; i <= n+1; i++) {
pan[i] = 0;
pan2[i] = 0;
head[i] = 0;
xian[i].next = xian[i].to = xian[i].value = 0;
}
for (int i = 1; i <=m*2+1; i++) {
xian[i].next = xian[i].to = xian[i].value = 0;
}
}
return 0;
}