记录编号 58347 评测结果 AAAAAAAAAA
题目名称 威尼斯旅行 最终得分 100
用户昵称 Gravatardigital-T 是否通过 通过
代码语言 C++ 运行时间 1.074 s
提交时间 2013-04-19 15:49:05 内存使用 9.97 MiB
显示代码纯文本
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
class adjtype
{
public:
	int u,v;
	long long w;
}adj[200001];
int n,m,q;
class cc
{
public:
	int ii;
	long long k;	
}quest[200001];
long long ans[200001],sum;
bool oj(adjtype a1,adjtype a2)
{
	if(a1.w<a2.w)return 1;
	return 0;
}
bool op(cc t1,cc t2)
{
	if(t1.k<t2.k)return 1;
	return 0;
}
class set//并查集的集合C
{
public:
	int parent;
	long long number;//count有几层,parent记录父亲节点,number记录这颗树总共有多少节点
}C[100001];
void makeset(int x)//集
{
	C[x].parent=-1;
	C[x].number=1;
}
int findset(int x)//查+压缩路径
{
	int y=x,z=x,tmp;
	while(C[z].parent!=-1)z=C[z].parent;
	while(C[y].parent!=-1)tmp=y,y=C[y].parent,C[tmp].parent=z;//路径压缩
	return z;
}
void merge(int x,int y)//并
{
	if(x==y)return;
	C[x].parent=y;
	C[y].number+=C[x].number;
}
int main()
{
	freopen("tripa.in","r",stdin);
	freopen("tripa.out","w",stdout);
	int i,j,k,l;
	scanf("%d%d%d",&n,&m,&q);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%lld",&adj[i].u,&adj[i].v,&adj[i].w);
	}
	sort(adj+1,adj+m+1,oj);
	for(i=1;i<=q;i++)//将查询的k值读入并排序
	{
		scanf("%lld",&quest[i].k);
		quest[i].ii=i;//记录排序前的标号
	}
	sort(quest+1,quest+q+1,op);
	quest[0].k=0;
	//======================================================处理读入
	for(i=1;i<=n;i++)makeset(i);
	j=1;sum=0;
	for(i=1;i<=q;i++)
	{
		while(j<=m&&adj[j].w<=quest[i].k)//没有用过这条边而且可以加进去
		{
			k=findset(adj[j].u);
			l=findset(adj[j].v);
			if(k!=l)
			{
				sum=sum-C[k].number*(C[k].number-1)/2-C[l].number*(C[l].number-1)/2;
				merge(k,l);
				sum+=C[l].number*(C[l].number-1)/2;
			}
			j++;
		}
		//---------------------------------------------------
		ans[quest[i].ii]=sum;
	}
	for(i=1;i<=q;i++)printf("%lld\n",ans[i]);
	//======================================================_=
	return 0;
}