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

题意:中文
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<limits.h>
typedef long long LL;
using namespace std;
const int INF=0x3f3f3f;

#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )

const int maxn=1100;
const int maxm=10000;
struct node{
    int u,v;
    int next;
}e[maxm];
int head[maxn],cntE;
int DFN[maxn],low[maxn];
int s[maxm],top,index,cnt;
int belong[maxn],instack[maxn];
int in[maxn],val[maxn];
int tt[maxn];//tt保存缩成的点中的最小值
int n,m;
void init()
{
    top=cntE=0;
    index=cnt=0;
    CLEAR(DFN,0);
    CLEAR(head,-1);
    CLEAR(instack,0);
}
void addedge(int u,int v)
{
    e[cntE].u=u;e[cntE].v=v;
    e[cntE].next=head[u];
    head[u]=cntE++;
}
void Tarjan(int u)
{
    DFN[u]=low[u]=++index;
    instack[u]=1;
    s[top++]=u;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].v;
        if(!DFN[v])
        {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(instack[v])
            low[u]=min(low[u],DFN[v]);
    }
    int v;
    if(DFN[u]==low[u])
    {
        cnt++;
        do{
            v=s[--top];
            belong[v]=cnt;
            instack[v]=0;
        }while(u!=v);
    }
}
void work()
{
    REPF(i,1,n)
      if(!DFN[i])  Tarjan(i);
    CLEAR(in,0);
    CLEAR(tt,INF);
    REPF(i,1,n)
    {
        if(tt[belong[i]]>val[i])
            tt[belong[i]]=val[i];
    }
    REPF(k,1,n)
    {
        for(int i=head[k];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(belong[k]!=belong[v])
               in[belong[v]]++;
        }
    }
    int ans=0;
    int num=0;
    REPF(i,1,cnt)
    {
        if(!in[i])
        {
            num++;
            ans+=tt[i];
        }
    }
    printf("%d %d\n",num,ans);
}
int main()
{
    int u,v;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        work();
    }
    return 0;
}
时间: 2024-10-25 21:52:40

HDU 1827 Summer Holiday(Tarjan缩点)的相关文章

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(强连通)

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 (强连通分量)

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

hdu1827Summer Holiday tarjan缩点

//给一个有向图,每个点都有权值,问最少需要几个起点和最少花费多少能将整个图遍历完 //用tarjan缩点,然后找出所有入度为0的点 #include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std ; const int maxn = 1010 ; const int inf = 0x7fffffff ; vector<int>

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 3639 Hawk-and-Chicken(Tarjan缩点+反向DFS)

Problem Description Kids in kindergarten enjoy playing a game called Hawk-and-Chicken. But there always exists a big problem: every kid in this game want to play the role of Hawk. So the teacher came up with an idea: Vote. Every child have some nice

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

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

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