HDU1827Summer Holiday (强连通,缩点,最小费用)

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

解题:首先用强连通,进行缩点,组成新的点集合,其中每个新点是一个强连通分量,求出新的点入度为0的个数就是所要求的最少要通知的人数。

#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
#define inf 99999999

int valu[1005],M[1005],node[1005],in[1005];
int low[1005],dfn[1005],tim,k;
int flog[1005],stack[1005],top;
vector<int>map[1005];
void init(int n)
{
    for(int i=1; i<=n; i++)
    {
        flog[i]=0; map[i].clear();
        in[i]=0; M[i]=inf;
    }
    k=0; tim=0; top=0;
}
void dfs(int v)
{
    stack[++top]=v; flog[v]=1;
    tim++; low[v]=dfn[v]=tim;
    for(int i=0; i<map[v].size(); i++)
    if(!flog[map[v][i]])
    {
        int u=map[v][i];
        dfs(u);
        low[v]=(low[v]<low[u])?low[v]:low[u];
    }
    else if(flog[map[v][i]]==1)
        low[v]=(low[v]<dfn[map[v][i]])?low[v]:dfn[map[v][i]];
    if(low[v]==dfn[v])
    {
        k++;
        int u;
        while(v!=stack[top])
        {
            u=stack[top--]; flog[u]=2; node[u]=k;
        }
        u=stack[top--]; flog[u]=2; node[u]=k;
    }
}
int MIN(int a,int b)
{
    return a>b?b:a;
}
int main()
{
    int n,m,a,b,ans,sum;
    while(scanf("%d%d",&n,&m)>0)
    {
        init(n);
        for(int i=1; i<=n; i++)
        scanf("%d",&valu[i]);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            map[a].push_back(b);
        }
        for(int i=1; i<=n; i++)
        if(flog[i]==0)
            dfs(i);
        for(int i=1; i<=n; i++)
        {
           M[node[i]]=MIN(valu[i],M[node[i]]);
            for(int j=0; j<map[i].size(); j++)
            {
                int u=map[i][j];
                if(node[i]!=node[u])
                    in[node[u]]++;
                M[node[u]]=MIN(M[node[u]],valu[u]);
            }
        }
        ans=0; sum=0;
        for(int i=1; i<=k; i++)
        if(in[i]==0)
        {
            ans++; sum+=M[i];
        }
        printf("%d %d\n",ans,sum);
    }
}

HDU1827Summer Holiday (强连通,缩点,最小费用)

时间: 2024-07-29 23:25:16

HDU1827Summer Holiday (强连通,缩点,最小费用)的相关文章

hdu3861The King’s Problem (强连通 缩点+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1606 Accepted Submission(s): 584 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cities in

HDU1827 Summer Holiday(强连通+缩点+最小传递费用)

题意:给出人物关系图,要把一个通知告诉所有人,告诉每一个人有一个费用,现在想知道最小通知的人与费用. 思路:利用Tarjan算法,对原图进行缩点,然后找出入度为0 的点,那么这个人是必须要通知的,由于经过缩点,所以,如果这个点是缩点来的,那就枚举下这个点里的任一个点,找到最小的费用点. #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<set

HDU3861-The King’s Problem(有向图强连通缩点+最小路径覆盖)

题目链接 题意:题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下: 1.有边u到v以及有边v到u,则u,v必须划分到同一个区域内. 2.一个区域内的两点至少要有一方能到达另一方. 3.一个点只能划分到一个区域内. 思路:根据规则1可知必然要对强连通分量进行缩点,缩点后变成了一个弱连通图.根据规则2.3可知即是要求图的最小路径覆盖. 代码: #include <iostream> #include <cstdio> #include <cstring&

Light OJ 1406 Assassin`s Creed 状态压缩DP+强连通缩点+最小路径覆盖

题目来源:Light OJ 1406 Assassin`s Creed 题意:有向图 派出最少的人经过全部的城市 而且每一个人不能走别人走过的地方 思路:最少的的人能够走全然图 明显是最小路径覆盖问题 这里可能有环 所以要缩点 可是看例子又发现 一个强连通分量可能要拆分 n最大才15 所以就状态压缩 将全图分成一个个子状态 每一个子状态缩点 求最小路径覆盖 这样就攻克了一个强连通分量拆分的问题 最后状态压缩DP求解最优值 #include <cstdio> #include <cstri

The King’s Problem (hdu 3861 强连通缩点+最小路径覆盖)

The King's Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2085    Accepted Submission(s): 741 Problem Description In the Kingdom of Silence, the king has a new problem. There are N cit

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 3861 The King&#39;s Problem(强连通分量缩点+最小路径覆盖)

http://acm.hdu.edu.cn/showproblem.php?pid=3861 题意: 国王要对n个城市进行规划,将这些城市分成若干个城市,强连通的城市必须处于一个州,另外一个州内的任意两个城市u,v,有从u到v的路径或从v到u的路径.求最少可以分成几个州. 思路: 这道题目挺好. 首先,强连通分量进行缩点,重新建图. 新建的图就是一个DAG图,接下来就转换成了最小路径覆盖问题. 最小路径覆盖就是用尽量少的不相交的简单路径覆盖DAG的所有顶点.每个顶点只属于一条路径,单个顶点也可以

NYOJ-120 校园网络 &amp;&amp;POJ 1236 (强连通缩点targan算法)

链接:click here 题意: 校园网络 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件.但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件. 现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理