题解:1 2,2 3,4 5,是朋友,所以可以坐一起,求最小的桌子数,那就是2个,因为1 2 3坐一桌,4 5坐一桌。简单的并查集应用,但注意题意是从1到n的,所以要减1。
代码:
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <string> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; typedef long long ll; typedef unsigned long long ull; #define prN printf(" ") #define SI(N) scanf("%d",&(N)) #define SII(N,M) scanf("%d%d",&(N),&(M)) #define SIII(N,M,K) scanf("%d%d%d",&(N),&(M),&(K)) #define cle(a,val) memset(a,(val),sizeof(a)) #define rep(i,b) for(int i=0;i<(b);i++) #define Rep(i,a,b) for(int i=(a);i<(b);i++) #define rank mrank const int MAX_BN=1005; int par[MAX_BN];// father int rank[MAX_BN],n,m;// deep void init(int n) { for (int i=0;i<n;i++) { par[i]=i; rank[i]=0;//并查集是从0开始的 高度也是从0开始的 } } //查询树的根 int myFind(int x) { if (par[x]==x) { return x; } else{ return par[x]=myFind(par[x]); } } //合并x和y所属的集合 void unite(int x,int y) { x=myFind(x); y=myFind(y); if (x==y) return; if (rank[x]<rank[y]) { par[x]=y; } else { par[y]=x; if (rank[x]==rank[y]) rank[x]++; } } //判断x和y是否属于同一集合 bool same(int x,int y) { return myFind(x)==myFind(y); } int a,b; int main() { #ifndef ONLINE_JUDGE freopen("C:\Users\Zmy\Desktop\in.txt","r",stdin); // freopen("C:\Users\Zmy\Desktop\out.txt","w",stdout); #endif // ONLINE_JUDGE int o; SI(o); while(o--) { SII(n,m); init(n); rep(i,m) { SII(a,b); unite(a-1,b-1); } int ans=0; rep(i,n) if (par[i]==i) ans++; cout<<ans<<endl; } return 0; }