#include#include using namespace std; const int N = 40010; int p[N]; int n,m; int find(int x) { if(p[x]!=x) p[x]=find(p[x]); return p[x]; } int get(int x,int y) { return x*n+y; } int main() { cin >> n >> m; int res; for(int i=0;i int x,y; int a,b; char op; cin >> x >> y >> op; x--,y--; a=get(x,y); if(op=='D') b=get(x+1,y); else b=get(x,y+1); int pa=find(a),pb=find(b); if(pa==pb){ res=i; break; } p[pa]=pb; } if(!res) puts("draw"); else cout << res << endl; return 0; }
思路:
图上的每个点都会对应一个二维坐标,我们将其转化为一维坐标方便计算和操作,转化公式见 g e t get get 函数,将画的边的起点和终点坐标分别表示出来,找各自的父节点,如果他们的父节点相同表示连通了,(如果不连通记得将这两个点合并为一个集合)即围成圈了。
例题:搭配购买#include例题:程序自动分析#include using namespace std; const int N = 10010; int n,m,vol; int p[N],v[N],w[N]; int f[N]; int find(int x) { if(p[x]!=x) p[x]=find(p[x]); return p[x]; } int main() { cin >> n >> m >> vol; for(int i=1;i<=n;i++) cin >> v[i] >> w[i]; for(int i=1;i<=n;i++) p[i]=i; while(m--) { int a,b; cin >> a >> b; int pa=find(a),pb=find(b); if(pa!=pb) { p[pa]=pb; v[pb]+=v[pa]; w[pb]+=w[pa]; } } for(int i=1;i<=n;i++)//枚举物品 { if(p[i]==i)//如果是根节点 { for(int j=vol;j>=v[i];j--)//枚举价钱(体积) { f[j]=max(f[j],f[j-v[i]]+w[i]); } } } cout << f[vol] << endl; return 0; }
有!
#include#include #include using namespace std; const int N = 2e6+10; int p[N]; int cnt; unordered_map mp; struct node{ int x,y,e; }query[N]; int get(int x) { if(!mp.count(x)) mp[x]=++cnt; return mp[x]; } int find(int x) { if(p[x]!=x) p[x]=find(p[x]); return p[x]; } int main() { int t; cin >> t ; while(t--) { cnt=0; mp.clear(); int n; cin>> n; for(int i=1;i<=n;i++) p[i]=i;//这里初始化要两倍的n呢QAQ for(int i=1;i<=n;i++){ int x,y,e; cin >> x >> y >> e; query[i]={get(x),get(y),e}; } for(int i=1;i<=n;i++) { if(query[i].e==1){ int pi=find(query[i].x),pj=find(query[i].y); p[pi]=pj; } } bool has_conflict=0; for(int i=1;i<=n;i++) { if(query[i].e==0){ int pa=find(query[i].x),pb=find(query[i].y); if(pa==pb) { has_conflict=1; break; } } } if(has_conflict) puts("NO"); else puts("YES"); } return 0; }
并查集+ 01 01 01背包
把需要搭配购买的放到一个集合,然后对所有集合进行 01 01 01背包
例题:银河英雄传说#include#include using namespace std; const int N = 3e4+10; int p[N],d[N],Size[N]; int find(int x) { if(p[x]!=x){ int root = find(p[x]); d[x]+=d[p[x]]; p[x]=root; } return p[x]; } int main() { int t; cin >> t; for(int i=0;i p[i]=i; Size[i]=1; } while(t--) { char op; int a,b; cin >> op >> a >> b; int pa=find(a),pb=find(b); if(op=='M'){ p[pa]=pb; d[pa]=Size[pb]; Size[pb]+=Size[pa]; } else { if(pa!=pb) puts("-1"); else cout << max(0, abs(d[a] - d[b]) - 1) << endl; } } return 0; }



