第一章、种类并查集
这是种类并查集的小图片,与并查集所不一样的是他的数组;和所需函数不同;应为对于种类之间的关系是不相同的。如上图所示
链接:例题:食物链:
这就是典型的种类并查集,加油思考!!!;
这道题也很难,搞不清楚状况,
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,k,t,x,y;
int ans=0;
int f[N];
int find(int n){//找祖先;
if(f[n]==n) return n;
return f[n]=find(f[n]);
}
void merge(int x,int y){//判断同类;
int fx=find(x);
int fy=find(y);
if(fx!=fy) f[fx]=fy;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++) f[i]=i;
while(k--){
cin>>t>>x>>y;
if(t==1) merge(x,y);
if(x>n||y>n){
ans++;
continue;
}
if(x==y&&t==2){
ans++;
continue;
}
if(find(x)==find(y)&&t==2){
ans++;
continue;
}
}
cout<<ans;
return 0;
}
这是一开始写出来的,仅仅只是简单的判断,但也有20分;接下来看ACcode:
#include<bits/stdc++.h>
using namespace std;
const int N=50005;//就是10^4+7;这是由n的数据范围规定的;
int n,k,x,y,ch;//n是个数,k是说话的个数,xy是两个动物的编号 ch执行的关系;
int ans,f[3*N];;//假话的数量 //有三种关系;
inline int find(int x){
if(f[x]==x) return x;//假如说,n的朋友或敌人是自己,就是return自己;
return f[x]=find(f[x]);//这是路径优化;也等同:
/*f[n]=find(f[x]);
return f[x];*/
}
inline bool check(int x,int y){//判断祖先的关系
int f1=find(x);
int f2=find(y);
if(f1==f2) return true;//如果x和y的朋友或敌人是同一人,就return true;
return false;//否则return false;
}
inline void merge(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx==fy) return;//如果两个值相等,那么就是假话,不需要合并;
if(fx<fy) f[fy]=fx;
else f[fx]=fy;//保证单项合并(小的向大的靠拢)
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;//简单输入
for(int i=1;i<=3*n;i++) f[i]=i;//初始值要附上,n<<1是2*n的意思;
while(k--){
cin>>ch>>x>>y;
if(x>n||y>n){
ans++;
continue;//如果说已经是假话了,之后就不用再判断了;
}
if(x==y){//当前的话中 x吃x就是假话;
if(ch==2) ans++;
continue;
}
if(ch==1){//一类型中 、朋友关系
if(check(x+n,y)||check(x,y+n)){
ans++;
continue;
}
merge(x,y);
merge(x+n,y+n);
merge(x+(n<<1),y+(n<<1));//合并三个类型;
}
if(ch==2){//二类型中 、敌对关系
if(check(x,y)||check(x+n,y)){//但又存在朋友关系
ans++;
continue;
}
merge(x,y+n);
merge(x+n,y+(n<<1));
merge(x+(n<<1),y);//依旧合并三个类型;
}
}
cout<<ans;
return 0;
}
详解尽在代码中!!!
其实这也不是很难
不过是加了个
inline bool check(int x,int y){//判断祖先的关系
int f1=find(x);
int f2=find(y);
if(f1==f2) return true;//如果x和y的朋友或敌人是同一人,就return true;
return false;//否则return false;
}
仅此而已,只是情况太多了;加油删除线格式