BZOJ 3060: [Poi2012]Tour de Byteotia 并查集
前 $k$ 个节点形成的结构必定是森林,而 $[k+1,r]$ 之间肯定是都连上,而剩下的一个在 $[1,k],$一个在 $[k+1,r]$ 的节点就能连多少连多少即可.
Code:
#include <bits/stdc++.h> #define N 1000005 #define setIO(s) freopen(s".in","r",stdin) using namespace std; struct Edge { int u,v; }e[N<<1]; int p[N]; int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } int main() { // setIO("input"); int n,m,k,i,j,cnt=0; scanf("%d%d%d",&n,&m,&k); for(i=1;i<=n;++i) p[i]=i; for(i=1;i<=m;++i) { scanf("%d%d",&e[i].u,&e[i].v); if(e[i].u>e[i].v) swap(e[i].u,e[i].v); if(e[i].v<=k) { int xx=find(e[i].u),yy=find(e[i].v); if(xx!=yy) { p[xx]=yy; ++cnt; } } else if(e[i].u>k) { ++cnt; int xx=find(e[i].u),yy=find(e[i].v); p[xx]=yy; } } for(i=1;i<=m;++i) { if(e[i].u<=k&&e[i].v>k) { int xx=find(e[i].u),yy=find(e[i].v); if(xx!=yy) p[xx]=yy,++cnt; } } printf("%d\n",m-cnt); return 0; }