20210810B

19 篇文章 0 订阅
该博客介绍了如何使用最小生成树算法来解决多人间情报交流的问题,目标是找到最经济的人员组合,使得每个人都能获取到所有情报,并计算派遣任务的最低总费用。通过实例演示和代码实现,展示了如何在有限的交流费用下完成任务规划。
摘要由CSDN通过智能技术生成

题目描述

n个人,每个人都有一份情报
人之间都可以交流,交流有对应的费用,交流完后各自享有对方的情报
A与B交流,A与C交流,B与C也可以互相享有
派遣n个人中任意一人去执行任务都有对应的费用
要求:派遣人去执行任务,派遣的人需要包含所有的情报(不一定只派遣一个),问最小花费

输入

第一行一个正整数n

接下来的n行包含n个不超过10^6的非负整数。
在k行m列的数字第k人和第m人会面的花费,同样的,与m行k列的数字相等,k=m时数字为0。
接下来的一行包含N个正整数Ai(1≤Ai≤10^6),分别为派遣1,2,…,N参加任务的花费。

输出

只有一行,为所需的最小总费用。

输入样例复制

输入1:

3
0 6 9
6 0 4
9 4 0
7 7 7

输入2:

3
0 17 20
17 0 10
20 10 0
15 9 12

输入3:

5
0 3 12 15 11
3 0 14 3 20
12 14 0 11 7
15 3 11 0 15
11 20 7 15 0
5 10 10 10 10

输出样例复制

输出1:

17

输出2:

34

输出3:

28

说明

30%:2<=n<=20
100%:2≤n≤1000
样例1:将会在1和2,接着2和3间举行会面,然后送2参与任务。
样例2:将会在2和3间举行会面,然后送1和2参与任务。
样例3:将会在2和4,接着1和2,接着3和5间举行会面,然后送1和3(或1和5)参与任务。

题解:

最小生成树模板,再加一个零号节点

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#define LL long long
#define ull unsigned LL
#define db double
#define ldb long db
#define re register
using namespace std;

const int N=1e6+100,M=2020;
struct sb
{
	int u,v,w;
} a[N];
int n,m,w,tot,num,ans,fa[N];
int in ( )
{
	int res=0,f=1;
	char ch;
	while ( ( ch=getchar ( ) ) < '0' || ch > '9' ) if ( ch=='-' ) f=-1;
	res=res*10+ch-48;
	while ( ( ch=getchar ( ) ) >='0' && ch<='9' ) res=res*10+ch-48;
	return res*f;
}
bool cmp ( sb a,sb b ) { return a.w<b.w; }
int find ( int x ) { return x==fa[x]?x:fa[x]=find ( fa[x] ); }
void unionn ( int x,int y,int sb )
{
	int fx=find ( x ),fy=find ( y );
	if ( fx==fy ) return;
//	printf ( "%d\n",a[sb].w );
	ans+=a[sb].w;
	fa[fx]=fy;
	num++;
}
int main ( )
{
	scanf ( "%d",&n );
	for ( int i=1;i<=n;i++ ) fa[i]=i;
	for ( int i=1;i<=n;i++ )
	{
		for ( int j=1;j<=n;j++ )
		{
			w=in();
			if ( i!=j ) a[++tot].u=i,a[tot].v=j,a[tot].w=w;
		}
	}
	for ( int i=1;i<=n;i++ )
	{
		w=in();
		a[++tot].u=0,a[tot].v=i,a[tot].w=w; 
	}
	sort ( a+1,a+1+tot,cmp );
//	printf ( "\n" );
//	printf ( "\n" );
//	for ( int i=1;i<=tot;i++ ) printf ( "%d %d %d\n",a[i].u,a[i].v,a[i].w );
//	printf ( "\n" );
//	printf ( "\n" );
	for ( int i=1;i<=tot;i++ )
	{
		unionn ( a[i].u,a[i].v,i );
		if ( num==n )
		{
			printf ( "%d",ans );
			return 0;
		}
	}
	return 0;
}

由于老师的NB评测机,不用快读就TLE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值