HDU 3047 Zjnu Stadium

一、题目

点此看题

题目描述

n n n个人, m m m个关系,每个关系描述为 A A A B B B顺时针距离为 d d d,每个询问由前面的关系为判定依据,如果错误则后面无视这个关系,问最后会有多少个错误的关系。

二、解法

带权并查集好题,我们先规定一个合并方向,也就是把 B B B合并到 A A A的上面,每个节点维护一个 d i s dis dis,表示到根的顺时针距离,我们现在考虑把 B B B并到 A A A上面的时候如何修改 d i s dis dis,请看下图。
在这里插入图片描述
容易发现 y y y r x rx rx的距离应该是 d x + m dx+m dx+m,已经有了一个 d y dy dy,所以在根处修改一个 d x + m − d y dx+m-dy dx+mdy

#include <cstdio>
const int M = 50005;
int read()
{	
	int x=0,flag=1;char c;
	while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
	while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*flag;
}
int T,n,m,ans,fa[M],dis[M];
int find(int x)
{
	if(x==fa[x]) return x;
	int t=fa[x];fa[x]=find(fa[x]);
	dis[x]+=dis[t];
	return fa[x];
}
int uni(int u,int v,int d)
{
	int x=find(u),y=find(v);
	if(x==y)
	{
		if(dis[u]+d!=dis[v]) return 1;
		return 0;
	}
	fa[y]=x;dis[y]=dis[u]+d-dis[v];
	return 0;
}
int main()
{
	while(~scanf("%d %d",&n,&m))
	{
		ans=0;
		for(int i=1;i<=n;i++)
		{
			fa[i]=i;dis[i]=0;
		}
		for(int i=1;i<=m;i++)
		{
			int x=read(),y=read(),d=read();
			ans+=uni(x,y,d);
		}
		printf("%d\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值