给出了 n 个人和 m 条关系,每一个团体的价值为当前团体的关系数-人数,如果这个团体的关系数小于等于人数那么就是 0 ,也就相当于不选择。
可以使用并查集来考虑对于每个节点计算点数和边数的关系,符合边数-点数>0的就加上边数-点数,最后求总和。
#pragma GCC optimize(1) #pragma GCC optimize(2) #pragma GCC optimize(3,"Ofast","inline") #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e6+100; int pre[maxn]; int p[maxn]; int z[maxn]; int find(int x) { if (pre[x] == x) return x; return pre[x] = find(pre[x]); } void marge(int a,int b){ int t1=find(a); int t2=find(b); p[t2]++; if(t1!=t2) { pre[t1]=t2; p[t2]+=p[t1]; z[t2]+=z[t1]; } } int a[maxn],b[maxn]; int main(){ int t,n,m; cin>>t; int kase=0; while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ p[i]=0; z[i]=1; pre[i]=i; } for(int i=1;i<=m;i++){ scanf("%d%d",&a[i],&b[i]); marge(a[i],b[i]); } int ans=0; for(int i=1;i<=n;i++){ if(pre[i]==i) ans+=max(0,p[i]-z[i]); } printf("Case #%d: ",++kase); cout<<ans<<endl; } }