(时隔多日回归刷题日常...)
P1111 修复公路
按时间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;
}
P2024 [NOI2001]食物链
巨简单的思路果然一交就挂,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;
}
