1. 程式人生 > >poj 2513 歐拉回路+並查集判斷是否聯通+Trie樹

poj 2513 歐拉回路+並查集判斷是否聯通+Trie樹

http://poj.org/problem?id=2513

最初看到 第一感覺---map  一看250000的資料量 果斷放棄

然後記得以前看過,trie代替map,尤其當資料量特別大的時候

學到了:

1、Trie代替map的思想,可以在單詞結尾的tree[i][tk]  這個i作為字串對應的int值 ,當然這個int值也可以用於建立並查集

2、接上,通過並查集判斷,所有的點在同一個集合圖就是聯通的,否則不聯通,注意tree[i][tk]>0 表示是單詞結尾,

    x=Find(x);//這句沒有的時候除錯了幾下。。。
    int flag=1;
    for(int i=1;i<top;i++)
    {
        if(tree[i][tk] && x!=Find(i))
        {
            flag=0;
            break;
        }
        if(tree[i][tk]%2)cnt++;
    }

注意,並查集並不保證所有在同一個集合的點的father相同,所以還是要通過Find(x)==Find(y)判斷是不是在同一個集合,而不能father相等判斷。。

3、無向圖尤拉通路存在的判定:

    a、聯通,並查集去做

   b、度數為奇數的個數為0或2---------------0 無向圖存在歐拉回路,2  無向圖存在尤拉通路 是半尤拉圖

#include<cstdio>
#include<cstring>
#include <string>
#include <map>
#include <iostream>
#include <cmath>
using namespace std;
#define INF 10000

const int tk=26,tb='a';
const int N = 5000000+1000;//2500000+1000;
//int d[N];
int tree[N][tk+1],top,n;
int father[N],pos[N],scnt;
char pat1[15],pat2[15];
void init()
{
    top=1;
    scnt=n=0;
    memset(tree[0],0,sizeof(tree[0]));
    //makeset
    for(int i=0;i<N;i++)
       father[i]=i;
}

int Insert(char *s, int Rank=0)
{
    int rt,nxt;
    for(rt=0; *s; rt=nxt,++s)
    {
        nxt=tree[rt][*s-tb];
        if(!nxt)
        {
            nxt=tree[rt][*s-tb]=top;
            memset(tree[top],0,sizeof(tree[top]));
            top++;
        }
    }
    tree[rt][tk]++;
    return rt;
}
int Find(int x)
{
    if(x!=father[x])father[x]=Find(father[x]);
    return father[x];
}
void Union(int x, int y)
{
    x=Find(x),y=Find(y);
    if(x==y)return;
    father[y]=x;
}
int main()
{
    //freopen("poj2513.txt","r",stdin);
    init();
    int cnt=0,x,y;
    while(scanf("%s%s",pat1,pat2)!=EOF)
    {
        x=Insert(pat1);
        y=Insert(pat2);
        Union(x,y);
    }
    x=Find(x);//這句沒有的時候除錯了幾下。。。
    int flag=1;
    for(int i=1;i<top;i++)
    {
        if(tree[i][tk] && x!=Find(i))
        {
            flag=0;
            break;
        }
        if(tree[i][tk]%2)cnt++;
    }
    if(!(
         cnt==2
         || cnt == 0)
       )flag=0;
    if(flag)printf("Possible\n");
    else printf("Impossible\n");
    return 0;
}