zoukankan      html  css  js  c++  java
  • 洛谷P2024食物链

    传送门啦

    这道题的特殊之处在于对于任意一个并查集,只要告诉你某个节点的物种,你就可以知道所有节点对应的物种。

    比如一条长为4的链 甲->乙->丙->丁 ,我们知道乙是A物种。那么甲一定是B物种,因为A只吃B物种,不吃C物种或是自己的同类。同样的丙一定是C物种,丁是B物种。

    也就是说,每一条链上都是A、B、C物种循环,这也是我们寻找不合逻辑的假话的出发点。

    我们可以定义数组 $ dis[i] $ 表示节点i到根节点距离 $ mod3 $ 的结果帮助解题。

    我们统计谎话的数量,那么我们把谎话这样分类:

    第一类谎话,包括

    (1)自己吃自己的同类是谎话,表述为 $ flag2 , xy $

    (2)编号超出限制,表述为 $ x>n||y>n $ 。 第二类叫不弱智的谎话,包括 $ flag1 , flag2 $ 这样两类。

    (1)d==1。

    我们先要考虑x y是否在同一个并查集中,这是判断真假话的前提。

    如果 $ x y $ 不在同一个并查集中,那么关于他们的任何表述都可以是真的。

    如果我说1和6是同类,那么自然地,2与7,3与8,4与9成为同类。

    我们任意的选取两个数是同类都是符合的。

    下面我们要做的就是把两个并查集合并。

    $ d[f[x]]=(d[y]-d[x]+3)%3 $ ;//关于距离

    $ fa[fa[x]]=fa [y] $ ;//关于父亲

    如果x y在同一个并查集中,那么违反距离关系的话一定是假话。

    $ dis[x]!=dis[y] $ //关于距离

    (2) $ flag==2 $ 。

    还是先看x y是否在一个并查集中,如果不在,那么合并并查集;如果在,那么根据距离关系找出假话。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define re register
    using namespace std;
    const int maxn = 5 * 1e4;
    
    inline int read(){
    	char ch = getchar();
    	int f = 1 , x = 0;
    	while(ch > '9' || ch < '0') {if(ch == '-') f = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0' ;ch = getchar();}
    	return x * f;
    }
    
    int n,k,flag,x,y;
    int fa[maxn],dis[maxn],ans;
    
    inline void init(){
    	for(re int i = 1 ; i <= n ; ++i)
    		fa[i] = i;
    }
    
    inline int find(int x){
    	if(x != fa[x]) {
    		int father = fa[x] ;
    		fa[x] = find(fa[x]) ;
    		dis[x] = (dis[x] + dis[father]) % 3 ;
    	}
    	return fa[x];
    }
    
    int main(){
    	n = read(); k = read();
    	init();
    	for(re int i = 1 ; i <= k ; ++i) {
    		flag = read(); x = read(); y = read();
    		if(flag == 2 && x == y) {
    			ans++;
    			continue;
    		}
    		if(x > n || y > n) {
    			ans++;
    			continue;
    		}
    		if(flag == 1) {
    			if(find(x) == find(y)) {
    				if(dis[x] != dis[y])
    					ans++;
    			}
    			else {
    				dis[fa[x]] = (dis[y] - dis[x] + 3) % 3;
    				fa[fa[x]] = fa[y];
    			}
    		}
    		else {
    			if(find(x) == find(y)) {
    				if(dis[x] != (dis[y] + 1) % 3) 
    					ans++;
    			}
    			else {
    				dis[fa[x]] = (dis[y] - dis[x] + 4) % 3 ;
    				fa[fa[x]] = fa[y];
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    pspc命令使用(转)
    NSArray数组的使用常用方法(转)
    css兼容的问题 持续更新
    关于memcache
    drupal7 学习笔记(持续更新中...)
    JavaScript的继承 转载
    浏览器的缓存机制
    我的js单例模式
    javascript运行机制
    javascrpt绑定事件之匿名函数
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9930223.html
Copyright © 2011-2022 走看看