POJ-2153Colored Sticks解题报告+欧拉回路,字典树,并查集;

传送门:http://poj.org/problem?id=2513

题意:给你许多木棍,木棍两端都有颜色,问能不能首尾相接,要求颜色相同。

参考:https://www.cnblogs.com/kuangbin/archive/2012/08/07/2626223.html

思路:

由图论知识可以知道,无向图存在欧拉路的充要条件为:

①     图是连通的;

②     所有节点的度为偶数,或者有且只有两个度为奇数的节点。

图的连通可以利用并查集去判断。

度数的统计比较容易。

数据比较大,首先需要将颜色的字符串和数字一一对应起来。

虽然可以用map,但是map效率不高,肯定会超时的。

 

最好的办法的是建立字典树。

将字符串和数字一一对应起来。

 

注意本题的数据有没有木棒的情况,要输出Possible。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <iterator>

using namespace std;

#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back

#define Pll pair<ll,ll>
#define Pii pair<int,int>

#define fi first
#define se second

#define OKC ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;

/*-----------------show time----------------*/

const int tm = 26;
int col = 0;
struct trie{
    trie* nxt[tm];
    int last;
    trie()
    {
        memset(nxt,0,sizeof(nxt));
        last = 0;
    }
}*root;
int insert(char *s)
{
    trie * p = root;
    for(int i=0;s[i];i++)
    {
        if(!p->nxt[s[i] - 'a'])
            p->nxt[s[i]-'a'] = new trie;
        p = p->nxt[s[i]-'a'];
    }
    if(p->last)
        return p->last;
    else 
    {
        col++;
        return p->last = col;
    }
}
const int maxn = 5e5+9;
int deg[maxn];
int fa[maxn];
void init(){
    for(int i=1; i<maxn; i++)
        fa[i] = i; 
    root = new trie;
}
int f(int x)
{
    if(fa[x]==x)return x;
    else return fa[x] = f(fa[x]);
}
void uni(int x,int y)
{
    int px = f(x);
    int py = f(y);
    if(px==py)return ;
    fa[px] = py;
}   
int main(){
    char s1[100],s2[100];
    init();
    while(~scanf("%s%s",s1,s2))
    {
        // if(s1[0]==s2[0])break;
        int x = insert(s1),y = insert(s2);
        uni(x,y);
        deg[x]++;
        deg[y]++;
    }
    int cnt1 = 0,cnt2 = 0;
    for(int i=1; i<=col; i++)
    {
        if(fa[i]==i)cnt1++;
        if(deg[i]%2==1)cnt2++;
    }
    if((cnt1==0||cnt1==1)&&(cnt2==0||cnt2==2))
    {
        puts("Possible");
    }
    else puts("Impossible");
    return 0;
}
View Code

 

posted @ 2018-05-23 14:25  ckxkexing  阅读(138)  评论(0编辑  收藏  举报