UVALive 4815 || SYSU 2387 Kids' Wishes dfs+(字典树哈希)

传送门:题源较多,大家可以到BNU上搜下Kid's Wishes。

提议:有还多孩子,和很多愿望,每个愿望有2个数字,代表前一个编号的孩子和后一个坐相邻,问所有愿望实现,能都坐成一个圈。

思路:虽然孩子数量很大,但是愿望数并不是那么多,这里就不采用它的编号了,而是根据孩子出现的顺序重新编号,一开始用的map。这种方法在UVALive上可以过,不过在中山大学的oj就超时了,后来改成Trie树哈希做,就过了。

刚刚只是对编号的处理,下面考虑坐圈,在一个圈中,一个孩子最多和两个孩子相邻,如果出现第三个,则一定不可以。

还有在途中找圈,要么找不到,要么是所有孩子围成的圈,其它小圈则说明也不可以,这样一考虑就差不多了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
int num;
int fst[222222],next[222222],node[222222],en;
int d[222222];
int cnt[222222];
int m,n,tnum;
bool vis[222222];
bool flag;
struct Trie
{
    int c[11];
    int id;
}t[2222222];
void init()
{
    en=0;
    num=0;
    tnum=0;
    flag=0;
    memset(fst,-1,sizeof(fst));
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    memset(t[0].c,0,sizeof(t[0].c));
}
void add(int u,int v)
{
    next[en]=fst[u];
    fst[u]=en;
    node[en]=v;
    en++;
}
int trie(char *a)
{
    int l=strlen(a);
    int p=0;
    for(int i=0;i<l;i++)
    {
        if(t[p].c[a[i]-'0']==0)
        {
            t[p].c[a[i]-'0']=++tnum;
            memset(t[tnum].c,0,sizeof(t[tnum].c));
            t[tnum].id=0;
        }
        p=t[p].c[a[i]-'0'];
    }
    if(t[p].id==0)
    {
        t[p].id=++num;
    }
    return t[p].id;
}
void dfs(int u,int r)
{
    vis[u]=1;
    if(r==-1)d[u]=1;
    else
    {
        d[u]=d[r]+1;
        cnt[u]++;
    }
    for(int i=fst[u];i!=-1;i=next[i])
    {
        if(flag)return;
        int v=node[i];
        if(v==r)continue;
        if(!vis[v])
        {
            cnt[u]++;
            if(cnt[u]>2)
            {
                flag=1;
                return;
            }
            dfs(v,u);
        }
        else if(vis[v])
        {
            if(d[u]-d[v]==n-1||d[v]-d[u]==n-1||d[v]==d[u]+1)continue;
            else
            {
                flag=1;
                return;
            }
        }
    }
}
int main()
{
    char s1[20],s2[20];
    int u,v;
    while(scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0)break;
        init();
        for(int i=0;i<m;i++)
        {
            scanf("%s%s",s1,s2);
            u=trie(s1);
            v=trie(s2);
            add(u,v);
            add(v,u);
        }
        for(int i=1;i<=num;i++)
        {
            if(flag)break;
            if(!vis[i])
            {
                dfs(i,-1);
            }
        }
        if(flag)cout<<"N"<<endl;
        else cout<<"Y"<<endl;
    }
    return 0;
}


你可能感兴趣的:(DFS,trie,Baoge)