[tarjan+最小树形图] hdu 3072 Intelligence System

本文介绍了一种通过Tarjan算法结合最小树形图方法解决的情报传递问题。具体地,针对一个包含多个成员的情报组织,如何使得信息从领导者出发,以最低成本通知到每个成员。文章首先使用Tarjan算法找出强连通分量,接着建立缩点图,并最终求解最小树形图以确定最优通知路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3072

Intelligence System

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1479    Accepted Submission(s): 653


Problem Description
After a day, ALPCs finally complete their ultimate intelligence system, the purpose of it is of course for ACM ... ... 
Now, kzc_tc, the head of the Intelligence Department (his code is once 48, but now 0), is sudden obtaining important information from one Intelligence personnel. That relates to the strategic direction and future development of the situation of ALPC. So it need for emergency notification to all Intelligence personnel, he decides to use the intelligence system (kzc_tc inform one, and the one inform other one or more, and so on. Finally the information is known to all).
We know this is a dangerous work. Each transmission of the information can only be made through a fixed approach, from a fixed person to another fixed, and cannot be exchanged, but between two persons may have more than one way for transferring. Each act of the transmission cost Ci (1 <= Ci <= 100000), the total cost of the transmission if inform some ones in our ALPC intelligence agency is their costs sum. 
Something good, if two people can inform each other, directly or indirectly through someone else, then they belong to the same branch (kzc_tc is in one branch, too!). This case, it’s very easy to inform each other, so that the cost between persons in the same branch will be ignored. The number of branch in intelligence agency is no more than one hundred.
As a result of the current tensions of ALPC’s funds, kzc_tc now has all relationships in his Intelligence system, and he want to write a program to achieve the minimum cost to ensure that everyone knows this intelligence.
It's really annoying!
 

Input
There are several test cases. 
In each case, the first line is an Integer N (0< N <= 50000), the number of the intelligence personnel including kzc_tc. Their code is numbered from 0 to N-1. And then M (0<= M <= 100000), the number of the transmission approach.
The next M lines, each line contains three integers, X, Y and C means person X transfer information to person Y cost C. 
 

Output
The minimum total cost for inform everyone.
Believe kzc_tc’s working! There always is a way for him to communicate with all other intelligence personnel.
 

Sample Input
  
  
3 3 0 1 100 1 2 50 0 2 100 3 3 0 1 100 1 2 50 2 1 100 2 2 0 1 50 0 1 100
 

Sample Output
  
  
150 100 50
 

Source
 

Recommend
lcy   |   We have carefully selected several similar problems for you:   3069  3077  3070  3071  3073 
 

Statistic |  Submit |  Discuss |  Note
题目意思:

有n个人,告诉前者给后者传送信息的花费,如果两个人能互相传送信息,则这两个人传送信息免费。leader的编号为0.求leader的信息传到所有人的最小花费。

解题思路:

tarjan+最小树形图

先tarjan求强连通分量,然后缩点建图(题目保证是一棵树),然后求最小树形图(做法:把指向所有点的花费最小的边求和即可)

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 55000

int low[Maxn],dfn[Maxn],sta[Maxn],sc,bc,n,m,dep;
int in[Maxn],ans;
bool iss[Maxn];
bool vis[110];
vector<vector<int> >myv;
int edge[110][110];
int ex[2*Maxn],ey[2*Maxn],ev[2*Maxn];

void tarjan(int cur)
{
    int ne;

    low[cur]=dfn[cur]=++dep;
    sta[++sc]=cur;
    iss[cur]=true;

    for(int i=0;i<myv[cur].size();i++)
    {
        int ne=myv[cur][i];
        if(!dfn[ne])
        {
            tarjan(ne);
            if(low[ne]<low[cur])
                low[cur]=low[ne];
        }
        else if(iss[ne]&&dfn[ne]<low[cur])
            low[cur]=dfn[ne];
    }
    if(low[cur]==dfn[cur])
    {
        ++bc;
        do
        {
            ne=sta[sc--];
            iss[ne]=false;
            in[ne]=bc;
        }while(ne!=cur);
    }
}
void solve()
{
    dep=sc=bc=0;
    memset(iss,false,sizeof(iss));
    memset(dfn,0,sizeof(dfn));

    for(int i=0;i<n;i++)
        if(!dfn[i])
            tarjan(i);
}


int main()
{
    //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   while(~scanf("%d%d",&n,&m))
   {
       myv.clear();
       myv.resize(n+1);

       for(int i=1;i<=m;i++)
       {
           scanf("%d%d%d",&ex[i],&ey[i],&ev[i]);
           myv[ex[i]].push_back(ey[i]);
       }
       solve();
       memset(edge,INF,sizeof(edge));
       for(int i=1;i<=m;i++)
       {
           int a=ex[i],b=ey[i];

           if(in[a]!=in[b])
               edge[in[a]][in[b]]=min(edge[in[a]][in[b]],ev[i]);
       }
       memset(vis,false,sizeof(vis));
       vis[in[0]]=true;
       int ans=0;

       for(int i=1;i<bc;i++)
       {
           int temp=INF,re;

           for(int j=1;j<=bc;j++)
                for(int k=1;k<=bc;k++)
                {
                    if(!vis[k]&&edge[j][k]<temp)
                    {
                        temp=edge[j][k];
                        re=k;
                    }
                }
           ans+=temp;
           vis[re]=true;
       }
       printf("%d\n",ans);

   }
    return 0;
}


### 有向图最小生成树的Tarjan算法 #### 定义与概念 在讨论有向图中的最小生成树之前,需先澄清一些基本概念。对于有向图而言,“最小生成树”的表述并不完全适用;更确切地说,应探讨的是**最小树形图**的概念。最小树形图是指以某个特定顶点作为根节点的一棵有向树,该树覆盖除根外的所有其他顶点,并使得这些边上的权重总和达到最小值[^3]。 #### Tarjan算法概述 尽管Tarjan算法主要用于寻找有向图中的强连通分量,但在某些情况下也可以被扩展用于构建最小树形图。然而需要注意的是,直接利用Tarjan算法来计算最小树形图并不是最常用的方法。通常提到的求解最小树形图的经典方法是朱刘算法。不过,在处理复杂网络结构时,Tarjan算法可以作为一种辅助工具帮助识别潜在的关键路径或子图特性。 #### 应用实例分析 考虑到Tarjan算法本身不是专门用来解决最小树形图问题的技术手段,因此这里提供一个基于Tarjan算法框架下间接支持最小树形图查找的例子: 假设在一个大型社交平台中存在大量用户之间的关注关系形成了一张复杂的有向加权图(每条边上带有表示互动频率或其他度量标准的数值),此时想要找出某位明星用户的影响力传播链路——即从这位明星出发能够影响到尽可能多粉丝群体的同时保持整体关联强度最大化的方案。这时就可以借助Tarjan算法快速定位出由该名星及其直系/间接下属构成的一个个独立社区(即强联通分支),再进一步运用诸如动态规划等策略评估并挑选最优组合方式达成目标。 ```python def tarjan_scc(graph): index_counter = [0] stack = [] lowlinks = {} index = {} result = [] def strongconnect(node): # Set the depth index for this node to be the next available counter. index[node] = index_counter[0] lowlinks[node] = index_counter[0] index_counter[0] += 1 stack.append(node) try: successors = graph[node] except KeyError: successors = [] for successor in successors: if successor not in lowlinks: # Successor has not yet been visited; recurse on it strongconnect(successor) lowlinks[node] = min(lowlinks[node], lowlinks[successor]) elif successor in stack: # The successor is already in the stack and hence part of current SCC lowlinks[node] = min(lowlinks[node], index[successor]) # If `node` is a root node, pop the stack and generate an SCC if lowlinks[node] == index[node]: connected_component = [] while True: successor = stack.pop() connected_component.append(successor) if successor == node: break component = tuple(connected_component) result.append(component) for node in graph.keys(): if node not in lowlinks: strongconnect(node) return result ``` 此代码片段展示了如何使用Tarjan算法检测给定有向图内的所有强连通分量。虽然这段代码并未直接涉及最小树形图的具体实现细节,但它提供了关于如何组织数据以及遍历过程的基础思路,这对于后续开发针对最小树形图优化的功能模块非常有用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值