HDU1827:Summer Holiday(缩点 & 贪心)

来源:互联网 发布:58网络公关公司 编辑:程序博客网 时间:2024/05/19 06:14

Summer Holiday

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


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 162 2 2 2 2 2 2 2 2 2 2 2 1 33 22 13 42 43 55 44 66 47 47 127 88 78 910 911 10
 

Sample Output
3 6
 

Author
威士忌
 

Source
HDOJ 2007 Summer Exercise(3)- Hold by Wiskey
 

思路:如果这是一个DAG图,威士忌只需联系所有入度为0的点,但是这里有环,我们考虑把它变成无环的DAG,因为有些点集可以看成一个整体,联系其中一个其余都能收到消息,这就是强连通子图,把他们缩成一个点,缩点同时记录“点”内哪个点与威士忌的联系花费最少,缩完后再找入度为0的“点”即可。

# include <iostream># include <cstdio># include <cstring>using namespace std;const int maxn = 1e3+30;struct node{    int u, v, next;}edge[maxn<<2];int Next[maxn], belong[maxn], in[maxn], C[maxn], c[maxn], h, tot, cnt, ans;int dep[maxn], low[maxn], stk[maxn], is_stk[maxn];void add_edge(int u, int v){    edge[tot] = node{u,v,Next[u]};    Next[u] = tot++;}void init(){    tot = cnt = ans = h = 0;    memset(C, 0x3f, sizeof(C));    memset(dep, 0, sizeof(dep));    memset(in, 0, sizeof(in));    memset(is_stk, 0, sizeof(is_stk));    memset(low, 0, sizeof(low));    memset(Next, -1, sizeof(Next));    memset(belong, 0, sizeof(belong));}void dfs(int u){    dep[u] = low[u] = ++h;    stk[cnt++] = u;    is_stk[u] = 1;    for(int i=Next[u]; i!=-1; i=edge[i].next)    {        int v = edge[i].v;        if(!dep[v])        {            dfs(v);            low[u] = min(low[u], low[v]);        }        else if(is_stk[v] && dep[v] < low[u])            low[u] = dep[v];    }    if(dep[u] == low[u])    {        int j;        ++ans;        do        {            j = stk[--cnt];            is_stk[j] = 0;            belong[j] = ans;            C[ans] = min(C[ans], c[j]);        }while(j != u);    }}int main(){    int n, m;    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=1; i<=n; ++i) scanf("%d",&c[i]);        for(int i=0; i<m; ++i)        {            int a, b;            scanf("%d%d",&a,&b);            add_edge(a, b);        }        for(int i=1; i<=n; ++i)            if(!dep[i]) dfs(i);        for(int i=1; i<=n; ++i)        {            for(int j=Next[i]; j!=-1; j=edge[j].next)            {                int u=edge[j].u, v = edge[j].v;                if(belong[u] != belong[v])                ++in[belong[v]];            }        }        int sum = 0, man = 0;        for(int i=1; i<=ans; ++i)        {            if(in[i] == 0)            {                ++man;                sum += C[i];            }        }        printf("%d %d\n",man, sum);    }    return 0;}


原创粉丝点击