HDU 1827 Summer Holiday

Summer Holiday

Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1260    Accepted Submission(s): 569

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

 

Author
威士忌
 

 

Source
 

 

Recommend
威士忌   |   We have carefully selected several similar problems for you:  1824 1826 1822 1825 2767 
                                                                                                                                                                                                                    
 
思路:Tarjan求强连通分量+缩点,把所有的点加入相应的强连通分量,然后把一个强连通分量中所有的点缩成一个点(缩点),如果这个点的入度为零,
那么就必须选择一个点,否则就不需要选择任何一个点
 
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
int cast[1010];
int head[1010];
int temp[1010];
int dfn[1010];
int low[1010];
int stack[1010];
int is_one[1010];
int N,M,m;
int the_min_people;
int the_min_cast;
int the_min;
int the_number;
int a,b;
struct Node
{
    int t,next;
}Edge[2010];
int Tarbfs(int k,int lay,int& scc_num)
{
    temp[k] = 1;
    low[k] = lay;
    dfn[k] = lay;
    stack[++ m] = k;
    for(int i = head[k];i != 0;i = Edge[i].next)
    {
        if(temp[Edge[i].t] == 0)
        {
            Tarbfs(Edge[i].t,++ lay,scc_num);
        }
        if(temp[Edge[i].t] == 1)
              low[k] = min(low[k],low[Edge[i].t]);
    }
    if(dfn[k] == low[k])
    {
        scc_num ++;
        do
        {
            low[stack[m]] = scc_num;
            temp[stack[m]] = 2;
        }while(stack[m --] != k);
    }
    return 0;
}
int Tarjan(int n)
{
    int scc_num = 0,lay = 1;
    m = 0;
    memset(temp,0,sizeof(temp));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    for(int i = 1;i <= n;i ++)
    {
        if(temp[i] == 0)
            Tarbfs(i,lay,scc_num);
    }
    return scc_num;
}
int main()
{
    while(scanf("%d%d",&N,&M) != EOF)
    {
        memset(Edge,0,sizeof(Edge));
        memset(head,0,sizeof(head));
        memset(cast,0,sizeof(cast));
        the_min_cast = 0;
        the_min_people = 0;
        for(int i = 1;i <= N;i ++)
            scanf("%d",&cast[i]);
        for(int i = 1;i <= M;i ++)
        {
            scanf("%d%d",&a,&b);
            Edge[i].t = b;
            Edge[i].next = head[a];
            head[a] = i;
        }
        the_number = Tarjan(N);
        for(int i = 1;i <= the_number;i ++)
            is_one[i] = 0;
        for(int i = 1;i <= the_number;i ++)
        {
            int indegree = 0;
            for(int j = 1;j <= N;j ++)
            {
                for(int k = head[j];k != 0;k = Edge[k].next)
                {
                    if(low[Edge[k].t] == i && low[j] != i)
                    {
                        indegree = 1;
                        break ;
                    }
                }
                if(indegree == 1)
                    break ;
            }
            if(indegree == 0)
               is_one[i] = 1;
        }
        for(int i = 1;i <= the_number;i ++)
        {
            if(is_one[i] == 1)
            {
                the_min_people ++;
                the_min = 100000000;
                for(int j = 1;j <= N;j ++)
                {
                    if(low[j] == i && cast[j] < the_min)
                         the_min = cast[j];
                }
                the_min_cast += the_min;
            }
        }
        printf("%d %d\n",the_min_people,the_min_cast);
    }
    return 0;
}

 

 

posted on 2013-11-15 12:42  天使是一个善良的神  阅读(183)  评论(0编辑  收藏  举报

导航