zoukankan      html  css  js  c++  java
  • POJ 2513 Colored Sticks

    题目链接:

    题目大意:

    • 有一些木棍,木棍两端有不同的颜色;
    • 两个木棍能够排列到一块,当且仅当两个木棍相邻端点颜色一样;
    • 问这些木棍能否全部链接到一块;

    解题思路:

    • 首先,可以将每一个颜色,看做是一个点;
    • 木棍就可以看做为两个颜色之间的一条边;
    • 然后就可以组成一个图;
    • 问这个图是否是一个欧拉图;
    • 对于每一个颜色,可以用map映射成一个数字。但是由于数据过大,用map会超时,所以改为用一个字典树来映射。在C++11中可以用unordered_map来映射,复杂度按理说是可以。然后用并查集判断所有点是否在一个图中,然后记录端点的入度和出度就可以判断出结果

    字典树版本

    #include<iostream>
    #include<string.h>
    #include<vector>
    #include<string>
    #include<algorithm>
    using namespace std;
    
    const int N = 500007;
    
    vector<int>many(N, 0), Rank(N, 0), par(N);
    
    void init()
    {
        for(int i=0; i<N; ++ i)
            par[i] = i;
    }
    
    int Find(int x)
    {
        if(x == par[x])
            return x;
        else
            return par[x] = Find(par[x]);
    }
    
    void unite(int x, int y)
    {
        x = Find(x);
        y = Find(y);
        if(x == y)
            return ;
    
        if(Rank[x] < Rank[y])
            par[x] = y;
        else
        {
            par[y] = x;
            if(Rank[x] == Rank[y])
                Rank[x] ++;
        }
    }
    
    struct node
    {
        int x;
        node *next[26];
        node()
        {
            x = -1;
            for(int i=0; i<26; ++ i)
                next[i] = NULL;
        }
    };
    
    node *root = new node();
    
    
    void Insert(string &str, int n)
    {
        node *head = root;
        size_t i = 0;
        while( i < str.size())
        {
            if(head->next[str[i] - 'a'] == NULL)
                head->next[str[i] - 'a'] = new node();
            head = head->next[str[i] - 'a'];
            i ++;
        }
        head->x = n;
    }
    
    int Search(string &str)
    {
        node *head = root;
        size_t i = 0;
        while(i < str.size())
        {
            if(head->next[str[i] - 'a'] == NULL)
                return 0;
            head = head->next[str[i] - 'a'];
            i ++;
        }
        if(head->x == -1)
            return 0;
        return head->x;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
    
        init();
        string a, b;
        int n = 0;
        int x = 0, y = 0;
    
        while(cin >> a >> b)
        {
            x = Search(a);
            if(x == 0)
                Insert(a, x = ++ n);
            y = Search(b);
            if(y == 0)
                Insert(b, y = ++ n);
            many[x] ++, many[y] ++;
            unite(x, y);
        }
    
        x = 0, y = 0;
        for(int i=1; i<=n; ++ i)
        {
            if(par[i] == i)
                x ++;
            if(many[i]&1)
                y ++;
        }
        if(x > 1 || y == 1 || y > 2)
            cout << "Impossible" << endl;
        else
            cout << "Possible" << endl;
        return 0;
    }
    

    unordered_map版本

    #include<iostream>
    #include<string.h>
    #include<vector>
    #include<unordered_map>
    #include<string>
    #include<algorithm>
    using namespace std;
    
    const int N = 500007;
    
    int par[N], Rank[N];
    
    
    unordered_map<string, int>mp;
    vector<int>many(N, 0);
    
    void init()
    {
        for(int i=0; i<N; ++ i)
            par[i] = i, Rank[i] = 0;
    }
    
    int Find(int x)
    {
        if(x == par[x])
            return x;
        else
            return par[x] = Find(par[x]);
    }
    
    void unite(int x, int y)
    {
        x = Find(x);
        y = Find(y);
        if(x == y)
            return ;
    
        if(Rank[x] < Rank[y])
            par[x] = y;
        else
        {
            par[y] = x;
            if(Rank[x] == Rank[y])
                Rank[x] ++;
        }
    }
    
    
    int main()
    {
        ios::sync_with_stdio(false);
    
        init();
        string a, b;
        int n = 0;
        while(cin >> a >> b)
        {
            if(mp[a] == 0)
                mp[a] = ++ n;
            if(mp[b] == 0)
                mp[b] = ++ n;
            many[mp[a]] ++, many[mp[b]] ++;
            unite(mp[a], mp[b]);
        }
        int x = 0, y = 0;
        for(int i=1; i<=n; ++ i)
        {
            if(par[i] == i)
                x ++;
            if(many[i]&1)
                y ++;
        }
        if(x != 1 || y & 1 || y > 2)
            cout << "Impossible" << endl;
        else
            cout << "Possible" << endl;
        return 0;
    }
    
    
  • 相关阅读:
    Subway POJ
    Invitation Cards POJ
    Cow Contest POJ
    MPI Maelstrom POJ
    Wormholes POJ
    Currency Exchange POJ
    Codeforces Round #608 (Div. 2) D Portals
    AcWing 1052. 设计密码
    AcWing 1058. 股票买卖 V 状态机模型dp
    AcWing 1057. 股票买卖 IV 状态机模型dp
  • 原文地址:https://www.cnblogs.com/aiterator/p/6565692.html
Copyright © 2011-2022 走看看