P2500 [SDOI2012] 集合 题解

· · 题解

Introduction

# Solution $n$ 方过百万,暴力辗标算。 输入边的信息后将边按边权从小到大排序并开一个数组或 $set$ 记录每个点所属的集合。 接下来修改时,直接改数组就行了。 查询时只需要从边权最短的边依次检查,找到第一条满足条件的边输出。 最劣时间复杂度:$\Theta(mq)$。 ```cpp #include<bits/stdc++.h> using namespace std; #define int long long inline int read(){ int x=0; short f=1; char c=getchar(); while(c>57||c<48){ if(c==45) f=-1; c=getchar(); } while(c<58&&c>47){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } inline void write(int x){ if(x<0ll) putchar(45),x=~x+1; if(x>9ll) write(x/10); putchar(x%10|48); } struct edge{ int u,v,w; friend bool operator<(edge x,edge y){ return x.w<y.w; } }e[5000001]; int n,m,ans,q,dacty[1000001]; string s; signed main(){ n=read(); m=read(); for(int i=1;i<=m;i++){ e[i].u=read(); e[i].v=read(); e[i].w=read(); } sort(e+1,e+m+1); for(int i=1;i<=n;i++) dacty[i]=1; q=read(); while(q--){ cin>>s; if(s[0]=='M'){ int x=read(); if(s[4]=='A'){ dacty[x]=1; } else if(s[4]=='B'){ dacty[x]=2; } else if(s[4]=='C'){ dacty[x]=3; } } else{ ans=INT_MAX; if(s[3]=='A'&&s[4]=='A'){ for(int i=1;i<=m;i++){ if(dacty[e[i].u]==1&&dacty[e[i].v]==1){ ans=e[i].w; break; } } } else if(s[3]=='A'&&s[4]=='B'){ for(int i=1;i<=m;i++){ if((dacty[e[i].u]==1&&dacty[e[i].v]==2)||(dacty[e[i].u]==2&&dacty[e[i].v]==1)){ ans=e[i].w; break; } } } else if(s[3]=='A'&&s[4]=='C'){ for(int i=1;i<=m;i++){ if((dacty[e[i].u]==1&&dacty[e[i].v]==3)||(dacty[e[i].u]==3&&dacty[e[i].v]==1)){ ans=e[i].w; break; } } } else if(s[3]=='B'&&s[4]=='B'){ for(int i=1;i<=m;i++){ if(dacty[e[i].u]==2&&dacty[e[i].v]==2){ ans=e[i].w; break; } } } else if(s[3]=='B'&&s[4]=='C'){ for(int i=1;i<=m;i++){ if((dacty[e[i].u]==2&&dacty[e[i].v]==3)||(dacty[e[i].u]==3&&dacty[e[i].v]==2)){ ans=e[i].w; break; } } } else if(s[3]=='C'&&s[4]=='C'){ for(int i=1;i<=m;i++){ if(dacty[e[i].u]==3&&dacty[e[i].v]==3){ ans=e[i].w; break; } } } if(ans==INT_MAX){ printf("No Found!\n"); } else{ write(ans); printf("\n"); } } } return 0; } ``` ## [record](https://www.luogu.com.cn/record/149935752) 跑的最慢的也就 $131ms$。