并查集,大水题
直接代码:
#include<iostream>
using namespace std;
#include<cstdio>
#include<map>
const int maxn=100005;
int pre[maxn],val[maxn];
map<string,int> m;
inline int input()
{
char c;
int ret=0;
c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') ret=ret*10+c-'0',c=getchar();
return ret;
}
inline int find(int x)
{
if(pre[x]!=x)
pre[x]=find(pre[x]);
return pre[x];
}
inline void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy){
pre[fy]=fx;
val[fx]+=val[fy];
}
}
inline void init()
{
for(int i=1;i<=maxn;i++)
{
pre[i]=i;
val[i]=1;
}
}
int main()
{
int T,n,cnt,mx;
char a[25],b[25];
while(cin>>T){
while(T--){
init();
while(!m.empty())
m.clear();
n=input();
cnt=1;
for(int i=1;i<=n;i++){
scanf("%s%s",a,b);
if(!m[a]){
m[a]=cnt;
cnt++;
}
if(!m[b]){
m[b]=cnt;
cnt++;
}
Union(m[a],m[b]);
printf("%d\n",max(val[find(m[a])],val[find(m[b])]));
}
}
}
return 0;
}
一定要注意find函数的压缩时候的先记录在更新
和Union函数时候的,合并根节点的顺序。这两点都会影响结果。
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50005;
int pre[maxn],val[maxn];
void init(int n)
{
for(int i=1;i<=n;i++){
pre[i]=i;
val[i]=0;
}
}
int find(int x)
{
if(pre[x]==x) return x;
int t=pre[x];
pre[x]=find(pre[x]);
val[x]+=val[t];
return pre[x];
}
void Union(int x,int y,int dis)
{
int fx=find(x);
int fy=find(y);
pre[fy]=fx;
val[fy]=val[x]+dis-val[y];
}
int main()
{
int n,m,a,b,dis,ans;
while(~scanf("%d%d",&n,&m)){
init(n);
ans=0;
while(m--){
scanf("%d%d%d",&a,&b,&dis);
if(find(a)==find(b)){
if(val[a]+dis!=val[b]) ans++;
}
else Union(a,b,dis);
}
printf("%d\n",ans);
}
return 0;
}