【JZOJ3237】间谍派遣

description

你是M,一个雇佣N个标号为从1到N的间谍的情报机关的总管。每个间谍被派往不同的国家并在那获取重要情报。

如下是你的任务:

1.在部分间谍间组织会面。每次会面在两个间谍间进行,两个间谍交换他们自己获取的或从之前会面中得到的信息。因为在不同国家的两个间谍间组织机密会面很困难,所以每次秘密会面都有一个费用。

2.当所有会面结束后,选择一部分间谍参加拯救世界的任务。一个间谍k参加此项任务需要花费Mk。很重要的一点是,任务要成功,必须满足参加任务的间谍获取的情报聚集到一起包含了其他剩余间谍所有的信息。

请找出完成任务的最小花费,即组织会面和派遣间谍的费用之和。


analysis

  • ™的想什么费用流

  • 注意到每个间谍必须两两联通,然后要求边权和最小

  • 最小生成树


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 1005
#define MAXM 1000005
#define ll long long
#define reg register ll 
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

ll fa[MAXN];
ll n,tot,ans;

struct edge
{
	ll x,y,z;
}a[MAXM];

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline bool cmp(edge a,edge b){return a.z<b.z;}
inline ll getfa(ll x){return !fa[x]?x:fa[x]=getfa(fa[x]);}
int main()
{
	n=read();
	fo(i,1,n)fo(j,1,n)
	{
		ll x=read();
		if (i<j)a[++tot].x=i,a[tot].y=j,a[tot].z=x;
	}
	fo(i,1,n)a[++tot].x=i,a[tot].y=n+1,a[tot].z=read();
	sort(a+1,a+tot+1,cmp);
	fo(i,1,tot)
	{
		ll x=a[i].x,y=a[i].y;
		if (getfa(x)!=getfa(y))fa[getfa(x)]=getfa(y),ans+=a[i].z;
	}
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/horizonwd/p/11172495.html