HDU 1827


HDU - 1827
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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章