• Luogu P1892 [BOI2003]团伙


    P1892 [BOI2003]团伙

    题目描述

    1920年的芝加哥,出现了一群强盗。如果两个强盗遇上了,那么他们要么是朋友,要么是敌人。而且有一点是肯定的,就是:

    我朋友的朋友是我的朋友;

    我敌人的敌人也是我的朋友。

    两个强盗是同一团伙的条件是当且仅当他们是朋友。现在给你一些关于强盗们的信息,问你最多有多少个强盗团伙。

    输入输出格式

    输入格式:

     

    输入文件gangs.in的第一行是一个整数N(2<=N<=1000),表示强盗的个数(从1编号到N)。 第二行M(1<=M<=5000),表示关于强盗的信息条数。 以下M行,每行可能是F p q或是E p q(1<=p q<=N),F表示p和q是朋友,E表示p和q是敌人。输入数据保证不会产生信息的矛盾。

     

    输出格式:

     

    输出文件gangs.out只有一行,表示最大可能的团伙数。

     

    输入输出样例

    输入样例#1:
    6
    4
    E 1 4
    F 3 5
    F 4 6
    E 1 2
    

      

    输出样例#1:
    3
    

      


     

     

    先说一下思路:

    对于只有朋友信息的数据就不用说了。对于敌人的信息,我们可以给每一个人i设置一个敌人集合E[i],当输入i和j时,我们就把i和E[j]合并,把j和E[i]合并。

    值得一提的是,要注意空集的处理,所谓空集就是一开始的时候,每个人都没有敌人。

     

    昨天晚上做了一晚上卡在了50分,今天又接着来啃,问同学,同学说我的想法很对,叫我自己慢慢调(WCNM我要是调的出来就不找你了)

    没办法,慢慢找喽。

    先给大家看看我的50分的代码。

     

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int n, m, Ans, x, y;
    
    int f[1008], E[1008];
    
    char C;
    
    bool vis[1008];
    
    int find(int x) {
    	if(x == f[x]) return f[x];
    	else return f[x] = find(f[x]);
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for(int i=1; i<=n; i++) f[i] = i;
    	for(int i=1; i<=m; i++) {
    		cin>>C>>x>>y;
    		int xx, yy;	
    		if(C == 'E') {
    			if(E[x] != 0) {
    				f[y] = find(E[x]);
    			}
    			if(E[y] != 0) {
    				f[x] = find(E[y]);
    			}
    			E[x] = y, E[y] = x;
    		}
    		if(C == 'F') {
    			f[x] = find(y);
    		}
    	}
    	for(int i=1; i<=n; i++) {
    		if(!vis[find(i)]) {
    			vis[find(i)] = 1;
    			Ans++;
    		}
    	}
    	printf("%d", Ans);
    }
    

     

      

    不知道大家看出什么问题了没。

    没看出的同学可要小心了,

    看一下我的合并集合时候的操作,是不是把之前合并好的集合都打乱了。

    为什么?因为我合并时修改的是f[x]的值,而不是f[find(x)]的值,这就会导致很可怕的错误。

    往后的此类操作都是这样的。

    好了,说到这里该放上AC的代码了

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int n, m, Ans, x, y;
    
    int f[1008], E[1008];
    
    char C;
    
    bool vis[1008];
    
    int find(int x) {
    	if(x == f[x]) return x;
    	else return f[x] = find(f[x]);
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for(int i=1; i<=n; i++) f[i] = i;
    	for(int i=1; i<=m; i++) {
    		cin>>C>>x>>y;
    		if(C == 'E') {
    			if(E[x] != 0) {	
    				f[find(y)] = find(E[x]);
    			}
    			else E[x] = find(y);
    			if(E[y] != 0) {
    				f[find(x)] = find(E[y]);
    			}
    			else E[y] = find(x);
    		}
    		if(C == 'F') {
    			f[find(x)] = find(y);
    		}
    	}
    	for(int i=1; i<=n; i++) {
    		if(!vis[find(i)]) {
    			vis[find(i)] = 1;
    			Ans++;
    		}
    	}
    	printf("%d", Ans);
    }
    

      

     

     

  • 相关阅读:
    OC与Swift的区别二(常量、变量、运算符)
    OC与Swift的区别一(文件结构)
    OC对象的归档及解档浅析
    OC单例模式的实现
    oc文件基本读写及操作
    IOS之沙盒(Sandbox)机制
    IOS开发之KVC与KVO简述
    SpringMVC控制器配置文件
    spring常用的连接池属性文件配置
    Struts2文件上传方式与上传失败解决方式
  • 原文地址:https://www.cnblogs.com/bljfy/p/9085446.html
Copyright © 2020-2023  润新知