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 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

威士忌

题意不多说,先Tarjan缩点,然后求出每个联通块的入度,入度为0说明至少要给这个联通块中的某一个人打电话,费用取这个联通块中花费最小的那一个。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

const int MAXN = 20010;//点数
const int MAXM = 500010;//边数

struct Edge
{
    int to,next;
}edge[MAXM];

int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc
int Index,top;
int scc;//强联通分量的个数
bool Instack[MAXN];
int num[MAXN];//各个强联通分量包含的点的个数,数组编号为1~scc
//num数组不一定需要,结合实际情况

void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void Tarjan(int u)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;
    for (int i=head[u];i+1;i=edge[i].next)
    {
        v=edge[i].to;
        if (!DFN[v])
        {
            Tarjan(v);
            if (Low[u]>Low[v]) Low[u]=Low[v];
        }
        else if (Instack[v]&&Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if (Low[u]==DFN[u])
    {
        scc++;
        do{
            v=Stack[--top];
            Instack[v]=false;
            Belong[v]=scc;
            num[scc]++;
        }while (v!=u);
    }
}

void solve(int N)
{
    memset(DFN,0,sizeof(DFN));
    memset(Instack,false,sizeof(Instack));
    memset(num,0,sizeof(num));
    Index=scc=top=0;
    for (int i=1;i<=N;i++)      //点的编号从1开始
        if (!DFN[i])
            Tarjan(i);
}

int n,m;
int cost[MAXN],d[MAXN];

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);
#endif
    int i,j,u,v;
    while (~sff(n,m))
    {
        init();
        for (i=1;i<=n;i++)
            sf(cost[i]);
        for (i=0;i<m;i++)
        {
            sff(u,v);
            addedge(u,v);
        }
        solve(n);
        for (u=1;u<=n;u++)
        {
            for (i=head[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if (Belong[u]!=Belong[v])
                    d[Belong[v]]++;
            }
        }
        int NUM=0,ans=0;
        for (i=1;i<=scc;i++)
        {
            if (d[i]==0)
            {
                int Min=INF;
                for (j=1;j<=n;j++)
                {
                    if (Belong[j]==i&&Min>cost[j])
                        Min=cost[j];
                }
                ans+=Min;
                NUM++;
            }
        }
        pf("%d %d\n",NUM,ans);
    }
    return 0;
}

Source

HDOJ 2007 Summer Exercise(3)- Hold by Wiskey

Recommend

威士忌   |   We have carefully selected several similar problems for you:  1823 1824 1826 1269 1822

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 14:29:11

Summer Holiday (hdu 1827 强联通缩点)的相关文章

Proving Equivalences (hdu 2767 强联通缩点)

Proving Equivalences Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3743    Accepted Submission(s): 1374 Problem Description Consider the following exercise, found in a generic linear algebra

Intelligence System (hdu 3072 强联通缩点+贪心)

Intelligence System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1650    Accepted Submission(s): 722 Problem Description After a day, ALPCs finally complete their ultimate intelligence syste

POJ 1236 Network of School(强联通缩点)

Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the "receiving schools"). Note that if B is in the

ZOJ 3795 Grouping 强联通缩点+拓扑序+偏序集的最大链的大小

题意:有n个人,m个关系,关系是这两个人前一个人可以跟后一个比较. 那么问你我最少分多少组可以使这个组里的人都不可以比较. 只会强联通缩点,真特么不知道怎么做,想了一个小时,网上一看,还要会偏序集的东西,有一个叫Dilworth定理的东西. 定理1 令(X,≤)是一个有限偏序集,并令r是其最大链的大小.则X可以被划分成r个但不能再少的反链. 其对偶定理称为Dilworth定理: 定理2 令(X,≤)是一个有限偏序集,并令m是反链的最大的大小.则X可以被划分成m个但不能再少的链. 然后我们用到的是

[bzoj 1093][ZJOI2007]最大半联通子图(强联通缩点+DP)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1093 分析: 首先肯定是先把强联通全部缩成一个点,然后成了一个DAG 下面要知道一点:原图的最大半联通子图实际是上是新DAG图的一个最长链 然后就像拓扑排序一样(不过这是以出度为0的点优先,拓扑排序以入度为0的点优先),设f[i]表示以节点i为起始节点的最长链的长度,s[i]表示以节点i为起始节点的最长链的条数,然后就DP一样搞…… 注意: 1.缩点的时候有可能有重边,要注意判断 2

HDU 2767 强联通分量

点击打开链接 题意:问加多少边后图会变成强联通分量为1的图 思路:简单的强联通,缩点后找入度和出度就行了,水题 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; co

HDU 4685 强联通分量+网络流

点击打开链接 题意:与POJ 1904 极其相像的一道题目,POJ的将一个完备匹配图给了你,并给了你一组可能的情况,很简单,但是这道题目,给的既不是完备匹配也没有给出可行的匹配方案,难的不要不要的 思路:刚开始看以为是和1904一模一样呢,然而难度上升的真快,看了一下是13年的多校题目,过了10几个把,可想而知这难度不是我等能够A掉的,刚自己想的是只加王子使其变成完备匹配,然后WA了,对了说一下为什么非要变成完备匹配呢,因为这道题目里的王子和公主的数量并不一定相同,就算相同也有可能不是完备匹配,

2017 Multi-University Training Contest - Team 9 1005&amp;&amp;HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】

FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1060    Accepted Submission(s): 506 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any oth

HDU 2767-Proving Equivalences(强联通+缩点)

题目地址:HDU 2767 题意:给一张有向图,求最少加几条边使这个图强连通. 思路:先求这张图的强连通分量,如果为1,则输出0(证明该图不需要加边已经是强连通的了),否则缩点.遍历原图的所有边,如果2个点在不同的强连通分量里面,建边,构成一张新图.统计新图中点的入度和出度,取入度等于0和出度等于0的最大值(因为求强连通缩点后,整张图就变成了一个无回路的有向图,要使之强连通,只需要将入度=0和出度=0的点加边即可,要保证加边后没有入度和出度为0的点,所以取两者最大值) *#include <st