zoukankan      html  css  js  c++  java
  • 种类并查集

    北京大学OJ1182
    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 64641   Accepted: 18999

    Description

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。 
    现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 
    有人用两种说法对这N个动物所构成的食物链关系进行描述: 
    第一种说法是"1 X Y",表示X和Y是同类。 
    第二种说法是"2 X Y",表示X吃Y。 
    此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。 
    1) 当前的话与前面的某些真的话冲突,就是假话; 
    2) 当前的话中X或Y比N大,就是假话; 
    3) 当前的话表示X吃X,就是假话。 
    你的任务是根据给定的N(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。 

    Input

    第一行是两个整数N和K,以一个空格分隔。 
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
    若D=1,则表示X和Y是同类。 
    若D=2,则表示X吃Y。

    Output

    只有一个整数,表示假话的数目。

    Sample Input

    100 7
    1 101 1 
    2 1 2
    2 2 3 
    2 3 3 
    1 1 3 
    2 3 1 
    1 5 5
    

    Sample Output

    3

    source code:
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    std::vector<pair<int,int> > w;
    std::vector<pair<int,int> > d;
    int num,len,fakeNum;
    
    struct node{
        int relation;//和父亲的关系,涉及到两个和两个以上的种类
        int father;//父亲序号
        //int value;//用于需要统计的题
    };
    
    std::vector<node> nodes;
    
    void init(){
        for (int i = 0 ; i < num ; i++){
            node nn;
            nn.father = i;
            //nn.value = 1;
            nn.relation = 0;//0代表是同一类,1代表吃掉父亲,2代表被父亲吃掉
            nodes.push_back(nn);
        }
    }
    
    //不同题目这个函数会不同
    int getRelation(int a, int b ){//已知a = (x,y) b = (y,z),求c = (x,z)
        int c = 0;
        
        if(a == 0){
            return b;
        }
    
        if (a == 1){
            if(b == 0){
                return 1;
            }
            if(b == 1){
                return 2;
            }
            if(b == 2){
                return 0;
            }
        }
    
        if (a == 2){
            if(b == 0){
                return 2;
            }
            if(b == 1){
                return 0;
            }
            if(b == 2){
                return 1;
            }
        }
    }
    
    //不同题目这个函数会不同
    int reverseRalation(int a){
        if(a == 0){
            return 0;
        }
        if(a == 1){
            return 2;
        }
        if(a == 2){
            return 1;
        }
    }
    
    void updateNode(int x, int root){//这里假设x的父亲是根节点或者是根节点的孩子
        if (nodes[x].father == root){
            return;
        }
        
        int f = nodes[x].father;
        //relation和value更新,不同题目规则不同
        nodes[x].relation = getRelation(nodes[x].relation,nodes[f].relation);
        //nodes[f].value -= 1; 
        nodes[x].father = root;
    }
    
    int getRoot(int x){
        int fi = nodes[x].father;
        if (fi == x){
            return fi;
        }
        int re = getRoot(fi);
        
        updateNode(x,re);
        return re;
    }
    
    
    void mergeUpdate(int x,int y,int xr,int yr,int relation){
        nodes[yr].father = xr;
    
        //relation和value更新,不同题目规则不同
        int xTOyr = getRelation(relation,nodes[y].relation);
        int yrTOx = reverseRalation(xTOyr);
        int yrTOxr= getRelation(yrTOx,nodes[x].relation);
    
        nodes[yr].relation = yrTOxr;
        
        //nodes[xr].value += nodes[yr].value;
    }
    
    bool isHarmonious(int x, int y, int relation){
        int rTOy = reverseRalation(nodes[y].relation);
        int xTOy = getRelation(nodes[x].relation,rTOy);
        return relation == xTOy;
    }
    
    bool merge(int x , int y, int relation){
        int xr = getRoot(x);
        int yr = getRoot(y);
        if(xr == yr){
            return isHarmonious(x,y,relation);
        }
        else{
            mergeUpdate(x,y,xr,yr,relation);
            
            return true;
        }
    }
    
    bool judge(int x , int y){
        int xr = getRoot(x);
        int yr = getRoot(y);
        if (xr == yr){
            return true;
        }
        else{
            return false;
        }
    }
    
    int goodState(int type, int x, int y){
        if (x>num || y > num){
            return -1;
        }
        if (x==y && type!=1){
            return -1;
        }
        return type-1;
    }
    struct data
    {    
        int ty;
        int f;
        int s;
        
    };
    std::vector<data> all;
    
    void input(){
        fakeNum = 0;
        cin >> num >> len;
        
        init();
        for (int i = 0 ; i < len ; i ++){
            int ty;
            int f, s;
            scanf("%d%d%d",&ty,&f,&s);
            
            //cout << ty << " " << f << " " << s <<endl;
            data d;
            d.ty = ty;
            d.f = f;
            d.s = s; 
            all.push_back( d );
            // all.push_back(s);
            // if (ty == 1){
            //     d.push_back(make_pair<int,int>(f,s) );
            // }
            // else{
            //     w.push_back(make_pair<int,int>(f,s) );
            // }
            
        }
    
        for (int i = 0 ; i < len ; i ++){
            int ty = all[i].ty;
            int f  = all[i].f;
            int s  = all[i].s; 
            //cout << ty << " " << f << " " << s <<endl;
            int relation = goodState(ty , f , s);
            if (relation == -1){
                fakeNum++;
            }
            else{
                if (!merge(f-1,s-1,relation)){
                    fakeNum++;
                }
            }
        }
        //sort(all.begin(), all.end());
        //std::vector<int>::iterator nown = unique(all.begin(), all.end());
        //all.erase(nown,all.end());
        //re = 0;
    }
    
    void calc(){
    
    }
    
    void output(){
        cout << fakeNum;
        // cout <<num << " "<< len << endl;
    
        // for (int i = 0 ; i < d.size() ; i ++){
        //         cout << "1 "<<" " <<d[i].first << " " << d[i].second <<endl;
        // }
        // for (int i = 0 ; i < w.size() ; i ++){
        //         cout << "2 "<<" " <<w[i].first << " " << w[i].second <<endl;
        // }
        // for (int i = 0 ; i < all.size() ; i ++){
        //         cout << all[i]<< " ";
        // }
    }
    
    int main(){
        input();
        calc();
        output();
        return 0;
    }

    测例生成器:

    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <cstdlib>
    
    using namespace std;
    
    int N=50000,K = 100000;
    
    int main(){
        srand(unsigned(time(0)));
        cout << N <<  " " << K << endl;
        for (int i = 0 ; i < K ; i++){
            cout << rand()%2+1 << " " << rand()%int(N+double(N)*0.01)+1<< " " << rand()%int(N+double(N)*0.01)+1<<endl;
        }
        
    }
  • 相关阅读:
    PAT顶级 1024 Currency Exchange Centers (35分)(最小生成树)
    Codeforces 1282B2 K for the Price of One (Hard Version)
    1023 Have Fun with Numbers (20)
    1005 Spell It Right (20)
    1092 To Buy or Not to Buy (20)
    1118 Birds in Forest (25)
    1130 Infix Expression (25)
    1085 Perfect Sequence (25)
    1109 Group Photo (25)
    1073 Scientific Notation (20)
  • 原文地址:https://www.cnblogs.com/huangshiyu13/p/5878674.html
Copyright © 2011-2022 走看看