HDU 1827



HDU - 1827

Summer Holiday

Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u

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计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?

Input

多组测试数组,以EOF结束。

第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。

接下一行有N个整数,表示Wiskey联系第i个人的电话费用。

接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。

Output

输出最小联系人数和最小花费。

每个CASE输出答案一行。

Sample Input

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 

Sample Output

3 6 

Hint

Source

HDOJ 2007 Summer Exercise(3)- Hold by Wiskey

中文题,题意不解释了。

思路: 怎样找到最少的联系人数和最小的花费。其实就是求强连通分量 + 缩点。判断一下每个强连通分量的入度是否为0,如果为0的话,说明这个分量的所有人没有人联系到他们,因此联系这个强连通分量中花费最小的点即可。

AC代码: 上模板 23333

/*~~~~~~~~~~~~~~~
HDU 1827
   by mowenwen
     2015.8.28
~~~~~~~~~~~~~~~*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x7fffffff
#define maxn 1000+10
#define maxm 2000+10
struct Edge
{
  int next,v;
}edge[maxm];
int n,m,index,top,tot,scc;
int head[maxn],Stack[maxn],dfn[maxn],low[maxn],belong[maxn],cost[maxn];
int indegree[maxn], outdegree[maxn];
bool instack[maxn];
int Max(int a,int b)
{
  return a > b? a: b;
}
void init()
{
	memset(head, -1, sizeof(head));
	memset(instack, false, sizeof(instack));
	memset(dfn, -1, sizeof(dfn));
	memset(low, 0, sizeof(low));
	memset(indegree, 0, sizeof(indegree));
	memset(outdegree, 0, sizeof(outdegree));
	memset(belong, 0,sizeof(belong));
	tot = 0;
	index = 0;
	top = 0;
	scc = 0;
}
void addedge(int u,int v)
{
	edge[tot].next = head[u];
	edge[tot].v = v;
	head[u] = tot ++;
}
void tarjan(int u)
{
	int v;
	dfn[u] = low[u] = ++index;
	Stack[top ++] = u;
	instack[u] = true;
	for(int i = head[u];i != -1;i = edge[i].next)
	{
		v = edge[i].v;
		if(dfn[v] == -1)
		{
		  tarjan(v);
		  if(low[v] < low[u])
		   low[u] = low[v];
		}
		else
		{
		  if(instack[v] && dfn[v] < low[u])
		  {
		    low[u] = dfn[v];
		  }
		}

	}
	if(dfn[u] == low[u])
	{
		scc ++;
        int j;
		do
		{
		    j = Stack[--top];
			instack[j] = false;  //这里写错,wa了快20发,555555
			belong[j] = scc;
		}
		while(j != u);
	}
}
void solve()
{
	for(int i = 1;i <= n;i ++)
	{
	  if(dfn[i] == -1)
	  tarjan(i);
	}
}
int main()
{
	while(scanf("%d%d", &n, &m) != EOF)
	{
	  init();
	  for(int i = 1;i <= n;i ++)
		scanf("%d", &cost[i]);
	  while(m --)
	  {
	  	int a, b;
	  	scanf("%d%d", &a, &b);
	  	addedge(a, b);
	  }
	  solve();
	  for(int i = 1;i <= n;i ++)
	  {
		for(int j = head[i];j != -1;j = edge[j].next)
		{
			int u = i;
			int v = edge[j].v;
			if(belong[u] != belong[v])
			{
			  indegree[belong[v]] ++;
			}
		}
	  }
	  int ans = 0,cnt = 0;
	  int mincost;
	  for(int i = 1;i <= scc;i ++)
	  {
		mincost = inf;
		if(indegree[i] == 0)
		{
			cnt ++;
			for(int j = 1;j <= n;j ++)
			{
			  if(belong[j] == i)
			  {
			    mincost = min(mincost, cost[j]);
			  }
			}
			ans += mincost;
		}
	  }

	 printf("%d %d\n",cnt,ans);
	}
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 14:29:12

HDU 1827的相关文章

HDU 1827 Summer Holiday (强连通分量)

题目地址:HDU 1827 先缩点,缩完点后,找出入度为0的块就是需要传递的块.然后用块中花费最少的来当代表块中的花费.累加起来就行了. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #includ

HDU 1827 Summer Holiday(强连通)

HDU 1827 Summer Holiday 题目链接 题意:中文题 思路:强连通缩点,每个点的权值为强连通中最小值,然后入度为0的点就是答案 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <stack> using namespace std; const int N = 1005; const int INF

HDU 1827:Summer Holiday(强连通)

http://acm.hdu.edu.cn/showproblem.php?pid=1827 思路:强连通分量缩点后找入度为0的点,然后对于属于该强连通分量的找一个最小耗费的入口. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <queue> 6 #include <cmath> 7 #i

hdu 1827 Summer Holiday tarjan+缩点

题意:http://acm.hdu.edu.cn/showproblem.php?pid=1827 Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2050    Accepted Submission(s): 939 Problem Description To see a World in a Gra

hdu - 1827 Summer Holiday (强连通)

http://acm.hdu.edu.cn/showproblem.php?pid=1827 缩点后,统计入度为0的点有多少个,那么这些点都是需要被通知的,但是这些点可能也是被缩的,所以每次在这个点所属集合找一个最小值即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include

HDU 1827 Summer Holiday(Tarjan缩点)

Problem Description 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真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话

HDU - 1827 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真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了.他知道其他人也有一些别人

Summer Holiday (hdu 1827 强联通缩点)

Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2054    Accepted Submission(s): 941 Problem Description To see a World in a Grain of Sand And a Heaven in a Wild Flower, Hold Inf

Book---强连通分量

这几天一直在做强连通,现在总结一小下 1.定义 在一个有向图中,如果任意的两个点都是相互可达的,就说这个图是强连通的,有向图的极大强连通子图,称为强连通分量 2.求法 学的是白书上的tarjan算法 用到了DFS的时间戳 假设一个强连通分量C,其中的第一个点是 P,那么DFS下去,就一定能够找到一个K点,返回P点,这条DFS路径上的点就处于这个强连通分量C中 假如现在发现节点v,同时发现节点v最远只能够到达节点u,那么节点u就是这个强连通分量最先被发现的节点 这样就转化成了求一个点u最远能够到达