(时隔多日回归刷题日常...)
按时间sort一遍,每次合并两个节点,显然如果原先不连通那么合并之后联通块数量--。然后如果n==1就输出当前时间return。
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) using namespace std; const int M=2e5+5; struct node{ int x,y,t; }e[M]; int fa[M],n,m; inline int cmp(const node x,const node y){return x.t<y.t;} inline int getfa(int x){return fa[x]==x?x:getfa(fa[x]);} inline int read(){ int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } int main(){ n=read(),m=read(); For(i,1,m) e[i].x=read(),e[i].y=read(),e[i].t=read(); sort(e+1,e+m+1,cmp); For(i,1,n) fa[i]=i; For(i,1,m){ int fx=getfa(e[i].x),fy=getfa(e[i].y); if(fx!=fy) fa[fx]=fy,n--; if(n==1) {printf("%d\n",e[i].t);return 0;} } printf("-1\n"); return 0; }
巨简单的思路果然一交就挂,20分,但不知道错在哪里。
看了题解,学了带权并查集,一知半解吧,再去看几道题。
f[x]意义不变,re[x]记录关系AKA权值,没搞懂怎么推出来的。
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) using namespace std; const int M=1e5+5; int f[M],re[M]; int n,m,k,x,y,ans; int getfa(int a){ int fa=f[a]; if(a!=fa){ f[a]=getfa(fa); re[a]=(re[a]+re[fa])%3; return f[a]; } else return fa; } int main(){ cin>>n>>m; For(i,1,n) f[i]=i; while(m--){ cin>>k>>x>>y; if(x>n||y>n||(k==2&&x==y)){ans++;continue;} if(k==1){ int fx=getfa(x),fy=getfa(y); if(fx==fy&&re[x]!=re[y]){ans++;continue;} else if(fx!=fy){f[fx]=fy;re[fx]=(re[y]-re[x]+3)%3;} } if(k==2){ int fx=getfa(x),fy=getfa(y); if(fx==fy){ int rela=(re[x]-re[y]+3)%3; if(rela!=1){ans++;continue;} } else f[fx]=fy,re[fx]=(re[y]-re[x]+4)%3; } } cout<<ans<<endl; return 0; }
原文:https://www.cnblogs.com/jian-song/p/11720598.html