• 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
    ",the_min_people,the_min_cast);
        }
        return 0;
    }
     
  • 相关阅读:
    Python-24-Django(Model Form、Ajax、上传文件、KindEditor)
    P23-Django-model、Form补充 & 序列化
    P22-Django-Session、CSRF、Form、信号
    21-Python-Django进阶补充篇
    Python-Django进阶
    Python-18-Django 基础篇
    17-前端开发之jQuery
    15-前端开发之JavaScript
    14-前端开发之CSS
    14-前端开发之HTML
  • 原文地址:https://www.cnblogs.com/GODLIKEING/p/3425123.html
Copyright © 2020-2023  润新知