JZOJ4686. 【NOIP2016提高A组8.12】通讯

本文探讨了一个组织如何在有限的资金下,利用已有的通讯线路高效地将关键信息传递给所有分部的问题。通过采用Tarjan算法进行强连通分量分析,实现最小成本的消息传播方案。

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

Description
“这一切都是命运石之门的选择。”
试图研制时间机器的机关SERN截获了中二科学家伦太郎发往过去的一条短信,并由此得知了伦太郎制作出了电话微波炉(仮)。
为了掌握时间机器的技术,SERN总部必须尽快将这个消息通过地下秘密通讯网络,传达到所有分部。
SERN共有N个部门(总部编号为0),通讯网络有M条单向通讯线路,每条线路有一个固定的通讯花费Ci。
为了保密,消息的传递只能按照固定的方式进行:从一个已知消息的部门向另一个与它有线路的部门传递(可能存在多条通信线路)。我们定义总费用为所有部门传递消息的费用和。
幸运的是,如果两个部门可以直接或间接地相互传递消息(即能按照上述方法将信息由X传递到Y,同时能由Y传递到X),我们就可以忽略它们之间的花费。
由于资金问题(预算都花在粒子对撞机上了),SERN总部的工程师希望知道,达到目标的最小花费是多少。

Input
多组数据,文件以2个0结尾。
每组数据第一行,一个整数N,表示有N个包括总部的部门(从0开始编号)。然后是一个整数M,表示有M条单向通讯线路。
接下来M行,每行三个整数,Xi,Yi,Ci,表示第i条线路从Xi连向Yi,花费为Ci。
Output
每组数据一行,一个整数表示达到目标的最小花费。

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
0 0
Sample Output
150
100
50
【样例解释】
第一组数据:总部把消息传给分部1,分部1再传给分部2.总费用:100+50=150.
第二组数据:总部把消息传给分部1,由于分部1和分部2可以互相传递消息,所以分部1可以无费用把消息传给2.总费用:100+0=100.
第三组数据:总部把消息传给分部1,最小费用为50.总费用:50.

Data Constraint
对于10%的数据,保证M=N-1
对于另30%的数据,N ≤ 20 ,M ≤ 20
对于100%的数据,N ≤ 50000 ,M ≤ 10^5 ,Ci ≤ 10^5 ,数据组数 ≤ 5
数据保证一定可以将信息传递到所有部门。

分析

对于 10%的数据:

又是一个送分点,显然将所有边权相加即为答案。

对于另 30%的数据:

我们枚举保留哪些边,再取一个最小值即可。

时间复杂度:O(2^M)

对于100%的数据:

因为如果两个部门可以直接或间接地相互传递消息,

所以,只要两个点

它们在同一个强连通分量中,

它们的传递费用就可以忽略。

因此,我们可以用tarjan缩点,将一个强连通分量变成一个点。

只要在这个强连通分量中间,

有任意一个点被传递到消息,

那么,这个强连通分量就可以被视为已经收到了消息。

  • 现在问题就变成了,有一些点和一些有向边,选择一些边,使得这些点联通。

很显然,最后的连通图就是一棵树。

再从另一个方面想每一个点一定是有一条边来连接的,

所以最后的答案就是连入每个点的边边权最小的和。

code(c++)

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <stdlib.h>
#include <math.h>
#define ll long long
using namespace std;

int a[200003],next[200003],b[100003],n,m,x,y,ti,cnt,t,mi;
int low[100003],dfn[100003],z[1000003],g[50003],f[50003],ta;
int a1[100003][3];
bool bz[100003],bz1[100003];
long long ans;

void tarjan(int x)
{
    low[x]=dfn[x]=++ti;
    bz[x]=bz1[x]=1;
    z[++ta]=x;
    for (int i=b[x];i;i=next[i])
    {
        int y=a[i];
        if (!bz[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else
        if (bz1[y]) low[x]=min(low[x],dfn[y]);
    }
    if (dfn[x]==low[x])
    {
        cnt++;
        z[ta+1]=100000000;
        while (z[ta+1]!=x)
        {
            g[z[ta]]=cnt;
            bz1[z[ta]]=0;   
            ta--;
        }   
    }
}

int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    while(1)
    {
    scanf("%d%d",&n,&m);
    if((n==0)&&(m==0))return 0;
    memset(b,0,sizeof(b));
    memset(bz,0,sizeof(bz));
    memset(bz1,0,sizeof(bz1));
    memset(f,57,sizeof(f));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&t);

        a[i]=y;
        next[i]=b[x];
        b[x]=i;

        a1[i][0]=x;
        a1[i][1]=y;
        a1[i][2]=t;
    }
    ans=0;
    ti=ta=cnt=0;

    tarjan(0);


    for(int i=1;i<=m;i++)
    {
        int q=a1[i][1];
        if(g[a1[i][0]]!=g[q])f[g[q]]=min(f[g[q]],a1[i][2]);
    }
    for(int i=1;i<=cnt;i++)
        if(f[i]<=100000000)ans+=f[i];
    printf("%lld\n",ans);

    for(int i=1;i<=n;i++)
        printf("%d\n",g[i]);
}
}
资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 “STC单片机电压测量”是一个以STC系列单片机为基础的电压检测应用案例,它涵盖了硬件电路设计、软件编程以及数据处理等核心知识点。STC单片机凭借其低功耗、高性价比和丰富的I/O接口,在电子工程领域得到了广泛应用。 STC是Specialized Technology Corporation的缩写,该公司的单片机基于8051内核,具备内部振荡器、高速运算能力、ISP(在系统编程)和IAP(在应用编程)功能,非常适合用于各种嵌入式控制系统。 在源代码方面,“浅雪”风格的代码通常简洁易懂,非常适合初学者学习。其中,“main.c”文件是程序的入口,包含了电压测量的核心逻辑;“STARTUP.A51”是启动代码,负责初始化单片机的硬件环境;“电压测量_uvopt.bak”和“电压测量_uvproj.bak”可能是Keil编译器的配置文件备份,用于设置编译选项和项目配置。 对于3S锂电池电压测量,3S锂电池由三节锂离子电池串联而成,标称电压为11.1V。测量时需要考虑电池的串联特性,通过分压电路将高电压转换为单片机可接受的范围,并实时监控,防止过充或过放,以确保电池的安全和寿命。 在电压测量电路设计中,“电压测量.lnp”文件可能包含电路布局信息,而“.hex”文件是编译后的机器码,用于烧录到单片机中。电路中通常会使用ADC(模拟数字转换器)将模拟电压信号转换为数字信号供单片机处理。 在软件编程方面,“StringData.h”文件可能包含程序中使用的字符串常量和数据结构定义。处理电压数据时,可能涉及浮点数运算,需要了解STC单片机对浮点数的支持情况,以及如何高效地存储和显示电压值。 用户界面方面,“电压测量.uvgui.kidd”可能是用户界面的配置文件,用于显示测量结果。在嵌入式系统中,用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值