C++有向图的强连通分量—————Summer Holiday

题目描述:

To see a World in a Grain of Sand 
And a Heaven in a Wild Flower, 
Hold Infinity in the palm of your hand 
And Eternity in an hour. 
                  —— William Blake 

听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗? 

输入:

多组测试数组,以EOF结束。 
第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。 
接下一行有N个整数,表示Wiskey联系第i个人的电话费用。 
接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。 

输出:

输出最小联系人数和最小花费。 
每个CASE输出答案一行。 

输入样例:

12 16
2 2 2 2 2 2 2 2 2 2 2 2 
1 3
3 2
2 1
3 4
2 4
3 5
5 4
4 6
6 4
7 4
7 12
7 8
8 7
8 9
10 9
11 10

输出样例:

3 6

思路分析:

我们可以这么想,如果几个点是一个强连通分量,那么无论我们从哪里出发,他们都会被遍历。

所以通知他们的最小话费为点集中花费最小的。

之后我们为了操作简单,可以将一个强连通分量缩成一个点,点权为最小花费。

我们将所有的强联通分量进行如此的操作,则我们就可以得到一个新图。

那么,点之间的边就是原图中那个强连通分量中的点与不属于同一分量的点的边就是现边。

到了现在,如果点的入度大于0,那么我们也不需要他的花费,毕竟其他的也可以进入它。

代码实现:

#include
#include
#include
#include
#include
using namespace std;
int n,m,dfn[10005],low[10005],p1,p2,belong[10005],a[10005],ans;
vectorG[10005];
bool v1[10005],v[10005];
stackq;
void Tarjan(int u)
{
	p1++;
	low[u]=p1;
	dfn[u]=p1;
	v1[u]=1;
	q.push(u);
	for(int i=0;i

 

你可能感兴趣的:(强连通分量)