专题四1008

来源:互联网 发布:凡科建站能做seo吗 编辑:程序博客网 时间:2024/05/29 01:52

题目大意:

给出一个图,求出这个图的最大连通分量,然后这个连通分量最多只能有一个环,要求这个连通分量的权值之和最大。

输入:

测试实例有多个,每个测试实例的第一行输入两个数NM,分别代表图的顶点个数和边的数量。接下来输入M行代表M条边,每一行输入3个整数uvc,分别代表边的两个端点和这条边的权值。当输入的NM0时代表输入结束,不做任何处理。

输出:

最大权值

解题思路:

这道题依然是用并查集处理。和以往不同的是,这道题多了一个条件,允许图最多有一个环,以前是不准有环,这就需要用一个visit数组去标记是否有环。数组开始从1N初始化为-1,代表无环。至于具体的判断呢,循环每一条边,如果这条边两个端点全在一个连通分量中,判断是不是有环,没有环的话,加入此边,并将visit标记为1;如果不再一个连通分量中,判断两棵树是不是有环,都有环的话,循环下一条边;有一个有环的话,加入此边,并合并;如果两棵树都没有环的话,也加入此边,合并。具体操作过程见代码。

感想:

这道题倒是让我感觉蛮新颖的,前面几道题全是不准有环,然后这一道允许有一个环,这就加大了题目的难度,判断有无环让我很头疼,那么多的判断分支。

代码如下:

#include<iostream>

#include<algorithm>

using namespace std;

int point[100];

int visit[100];

struct Node

{

int x, y, length;

}e[100];

int find(int x)

{

if (x != point[x])

point[x] = find(point[x]);

return point[x];

}

bool cmp(Node n1,Node n2)

{

return n1.length >n2.length;

}

int main()

{

int n, m, ans;

while (cin >> n)

{

cin >> m;

if (n == 0 && m == 0)

break;

ans = 0;

for (int i = 0; i < n; i++)

{

point[i] = i;

visit[i] = -1;

}

for (int i = 0; i < m; i++)

cin >> e[i].x >> e[i].y >> e[i].length;

sort(e, e + m, cmp);

for (int i = 0; i < m; i++)

{

int fx = find(e[i].x);

int fy = find(e[i].y);

if (fx == fy)

{

if (visit[fx] == 1)

continue;

visit[fx] = 1;

}

else

{

if (visit[fx] == 1 && visit[fy] == 1)

continue;

else

if (visit[fx] == -1)

point[fx] = fy;

else

point[fy] = fx;

}

ans += e[i].length;

}

cout << ans << endl;

}

return 0;

}

0 0
原创粉丝点击