`
yzmduncan
  • 浏览: 330318 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

有向图——最小点基和最小权点基

 
阅读更多

    考虑这样一个问题:

    老师想通知他的所有学生一个消息,虽然他手上有他们的联系方式,但是一个一个联系太耗时间和电话费了。他知道其它人也有一些别人的联系方式,这样可以通知他人,再让他们去通知一下别人。现在要求出至少需要联系多少人,最少需要多少花费,使得所有的人都被通知到。

    上述问题可以抽象为:图G中,每个点都有一个权值,若a能联系到b,则连边(a,b)。选出最少的点数(或者权值最小),使从这些点能到达所有点。

    解:求图G的强连通分量,入度为0的强连通分量个数即为最小点基,从每个入度为0的强连通分量中取出权值最小的点,构成的集合即最小权点基。求强连通Trajan算法不再赘述。

 

例:HDU1827

/*
最小点基和最小权点基:
    最小点基=从每个入度为0的SCC中任意选出一个点的集合
    最小权点基=从每个入度为0的SCC中选出最小权值的点的集合
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x7fffffff;
const int MAX = 1005;
int n,m;
int node[MAX];
struct Edge
{
    int from;
    int to;
    int next;
};
Edge e[2005];
int head[MAX],edgeNum;

int dfn[MAX],low[MAX],seq;
int stack[MAX],top;
bool inStack[MAX];
int belong[MAX],cnt;
int ind[MAX];
int cost[MAX];

void addEdge(int from, int to)
{
    e[edgeNum].from = from;
    e[edgeNum].to = to;
    e[edgeNum].next = head[from];
    head[from] = edgeNum++;
}

int min(int a, int b)
{
    return a<b?a:b;
}

void Tarjan(int u)
{
    dfn[u] = low[u] = seq++;
    stack[top++] = u;
    inStack[u] = true;
    for(int i = head[u]; i != -1; i = e[i].next)
    {
        int w = e[i].to;
        if(dfn[w] < 0)
        {
            Tarjan(w);
            low[u] = min(low[u],low[w]);
        }
        else if(inStack[w])
            low[u] = min(low[u],dfn[w]);
    }
    if(dfn[u] == low[u])
    {
        int v;
        cnt++;
        do
        {
            top--;
            v =stack[top];
            inStack[v] = false;
            belong[v] = cnt;
        }while(u != v);
    }
}

void solve()
{
    int i;
    for(i = 1; i <= n; i++)
        if(dfn[i] < 0)
            Tarjan(i);
    for(i = 0; i < edgeNum; i++)
    {
        if(belong[e[i].from] != belong[e[i].to])
            ind[belong[e[i].to]]++;
    }
    for(i = 1; i <= n; i++)
    {
        if(cost[belong[i]] > node[i])
            cost[belong[i]] = node[i];
    }
    int result1=0,result2=0;
    for(i = 1; i <= cnt; i++)
    {
        if(ind[i]==0)
        {
            result1++;
            result2 += cost[i];
        }
    }
    printf("%d %d\n",result1,result2);
}

int main()
{
    int i;
    int from,to;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        edgeNum = seq = cnt = top = 0;
        memset(head,-1,sizeof(head));
        memset(dfn,-1,sizeof(dfn));
        memset(inStack,0,sizeof(inStack));
        memset(ind,0,sizeof(ind));
        for(i = 1; i <= n; i++)
            cost[i] = INF;
        for(i = 1; i <= n; i++)
            scanf("%d",&node[i]);
        for(i = 0; i < m; i++)
        {
            scanf("%d %d",&from,&to);
            addEdge(from,to);
        }
        solve();
    }
    return 0;
}

 

分享到:
评论

相关推荐

    数据结构报告——最小生成树

    最小生成树算法的目标是从一个加权无向图中找到一棵包括所有顶点的树,使得这棵树的所有边的权重之和尽可能小。这样的树被称为最小生成树。在实际应用中,这个概念广泛应用于电信网络规划、电路设计和运输路线规划等...

    Python图论算法实现工具——NetworkX(3)有向图、多图等图生成器及图的可视化1

    【Python图论算法实现工具——NetworkX(3)有向图、多图等图生成器及图的可视化1】 在图论中,图形是数据结构的一种抽象表示,用于描述对象之间的关系。Python中的NetworkX库提供了对各种图类型的支持,包括有向图...

    数据结构——最小生成树

    最小生成树使得一个加权无向图的所有节点通过边相连,且这些边的总权重最小。 普雷姆算法(Prim's Algorithm)是一种求解加权无向图最小生成树的经典算法,由捷克数学家Vojtěch Jarník提出,后由罗伯特·普雷姆...

    数据结构——图的最小生成树(邻接矩阵、普利姆)

    最小生成树是指在一个加权无向图中找到一棵包含所有顶点的生成树,使得这棵树的所有边的权重之和最小。本文将详细介绍如何通过普利姆算法,并利用邻接矩阵来求解无向图的最小生成树。 #### 邻接矩阵表示法 在图的...

    数据结构课程设计——最小生成树

    在一个加权无向图中,如果要连接所有的顶点,并使得所有边的总权重尽可能小,那么这个连接所有顶点的树就被称为最小生成树。常见的算法有克鲁斯卡尔(Kruskal's Algorithm)和普里姆(Prim's Algorithm)。 克鲁斯...

    数据结构——最小生成树C代码

    最小生成树的目标是从带权重的无向图中找出一棵包括所有顶点的树,使得树中所有边的权重之和尽可能小。 在C语言中,有多种算法可以用来构建最小生成树,其中最常用的两种是Prim算法和Kruskal算法。 1. Prim算法: ...

    数据结构——图

    根据边是否有方向,图可以分为**有向图**和**无向图**。 1. **哥尼斯堡七桥问题**:这是一个经典的数学问题,由莱布尼茨在1736年提出。问题描述为:从任一桥头出发,依次走过每座桥,每座桥只走一次,最后回到出发...

    美国硅谷城镇地图——最短路径问题

    最短路径问题可以被定义为:在带权无向图或有向图中寻找两个特定节点间路径的最小代价。在这个硅谷城镇地图问题中,我们可以假设图是有向的,因为通常交通网络都是单向的。权值可能代表距离、行驶时间或者其它相关的...

    运筹学——图与网络分析PPT学习教案.pptx

    图可以分为无向图和有向图两种,无向图由点和边所组成,表示为G=(V,E),有向图由点和弧所组成,表示为D=(V,A)。 2. 图上的基本概念 图上的基本概念包括边、弧、环、简单图、多重图等。边是一条不带箭头的连线,弧...

    头歌数据结构图的最小生成树算法

    根据给定文件的信息,本文将深入探讨两种构造最小生成树的经典算法——普里姆(Prim)算法与克鲁斯卡尔(Kruskal)算法,并通过具体的代码实现来展示这两种算法的应用场景与实现细节。 ### 一、最小生成树概念 #### ...

    山东大学软件学院数据结构课程设计——22.图的实现与分析分别对有向图

    最小生成树算法可以找到一个有向图中连接所有顶点的边集,使得这些边的总权重最小。经典的MST算法包括Prim算法和Kruskal算法。Prim算法从一个顶点开始,逐步添加边,确保每次添加的边都连接两个不同的连通分量,并且...

    课程设计——使n个城市连接的最小生成树系统

    在一个加权无向图中,最小生成树是指一个包括所有顶点的子集,使得这个子集中任意两个顶点间都有边相连,并且这些边的总权重最小。常见的算法有Prim算法和Kruskal算法。 1. **Prim算法**:从一个顶点开始,逐步将...

    算法分析与设计——无向图的应用(C++版).

    然后,和有向图相似的介绍了两种无向图的遍历方法(深度优先遍历和广度优先遍历)。接着介绍了迷宫问题的求解方法。最后,介绍了求解最短路径的六种方法,包括宽度优先搜索、动态规划、A﹡算法、等代价搜索法、...

    451(1)最基本的图形——点与线.ppt

    在建立车站C时,使其到A和B的距离之和最小,C点应位于A、B两点连线的中垂线上;从A到B有两条路,这两条路的长度关系可以通过比较来确定;若要开辟第三条最短路径,应连接A、B两点的中点。 通过练习,我们可以知道过...

    最小生成树——prim

    Prim算法主要用于找到一个加权无向图的最小生成树,即从图中选取一组边,使得这些边连接了图中的所有顶点,并且这组边的总权重最小。这个过程可以看作是在构建一个覆盖所有顶点的树,而代价是最小的。 1. 工作原理...

    数据结构——图.ppt

    根据边是否有方向,图可以分为有向图和无向图。在有向图中,每条边都有明确的方向,用尖括号表示,如 `, v2&gt;` 表示从顶点 v1 指向顶点 v2 的有向边。无向图的边没有方向,用圆括号表示,如 `(v1, v2)` 表示顶点 v1 ...

Global site tag (gtag.js) - Google Analytics