格子游戏
思路:首先围成一个闭环的时候,两个点一定有边相连,那么可以把这两个点通过并查集连在一个连通块里面,如果两个点的父亲相同,那么就形成闭环。同时,为了方便可以将二维的图转化成一维的进行计算,k=x*n+y,x,y要从0开始统计。
代码附上:
#include <bits/stdc++.h>
using namespace std;
const int N =1e5+5;
int n,m;
int pre[N];
int root(int x){
return pre[x]=(pre[x]==x)?x:root(pre[x]);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=0;i<=n*n;i++)pre[i]=i;
int ans=0;
bool flag = true;
while(m--){
ans++;
char dir;
int x,y;cin>>x>>y>>dir;
x--,y--;
int k=x*n+y;
if(dir=='D'){
int p=(x+1)*n+y;
int fx=root(k);
int fy=root(p);
if(fx!=fy){
pre[fx]=fy;
}
else{
flag = false;
break;
}
}
else {
int p=x*n+y+1;
int fx=root(k);
int fy=root(p);
if(fx!=fy){
pre[fx]=fy;
}
else {
flag = false;
break;
}
}
}
if(flag)cout<<"draw"<<"\n";
else cout<<ans<<"\n";
return 0;
}
搭配购买
思路:买一朵云则与这朵云有搭配的云都要买,可以把这几朵云看成一个连通块,可用并查集的方式进行合并,然后用01背包问题去解决,问题的关键在于如何表示成01背包,通过并查集将每个云朵的根表示,然后根的价值和价格加上该节点的价值和价格,需重新循环一遍叠加。
代码附上:
#include <bits/stdc++.h>
using namespace std;
const int N =1e5+5;
int n,m,tot;
int pre[N],w[N],v[N];
int f[N];
int root(int x){
return pre[x]=(pre[x]==x)?x:root(pre[x]);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>tot;
for(int i=1;i<=n;i++){
cin>>v[i]>>w[i];
}
for(int i=1;i<=n;i++)pre[i]=i;
for(int i=1;i<=m;i++){
int x,y;cin>>x>>y;
int fx=root(x);
int fy=root(y);
if(fx!=fy){
pre[fx]=fy;
}
}
for(int i=1;i<=n;i++){
int fx=root(i);
if(fx!=i){
w[fx]+=w[i];
v[fx]+=v[i];
}
}
for(int i=1;i<=n;i++){
if(root(i)!=i)continue;
for(int j=tot;j>=v[i];j--){
f[j]=max(f[j],f[j-v[i]]+w[i]);
}
}
cout<<f[tot]<<"\n";
return 0;
}