您的位置:首页 > 其它

POJ 2513 Colored Sticks (Tire+欧拉路+并查集)

2015-08-11 21:35 375 查看
Colored Sticks

Time Limit: 5000MSMemory Limit: 128000K
Total Submissions: 32788Accepted: 8639
Description

You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?
Input

Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.
Output

If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
Sample Input
blue red
red violet
cyan blue
blue magenta
magenta cyan

Sample Output
Possible


题目大意: 判断已给的棍子是否可以调整成一条直线。(前提是相接的部分是同一颜色)

思路:若要使颜色有相同的,颜色数必须为偶数。分别用两段字符串建立Tire,利用标记变量分别在建树完成后返回该颜色的建树编号。

利用此编号来记录当前颜色出现的次数,与此同时,利用并查集,看是否是连通图。判断如果颜色出现的次数为一个奇数或奇数的个数>2者直接Impossible,

否则再判断连通性,如果有颜色的跟节点不是最开始的数(在里为1),也是Impossible,否则为possible

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#define SUM 250001
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;

struct node
{
    int flag;
    node *next[27];
} ;
int f[500010],cnt,s,du[500010];
char s1[16],s2[16],now[32];

node *init()
{
    node *p;
    p=new node ;
    for(int i=0; i<26; i++)
        p->next[i]=NULL;
    p->flag=0;
    return p;
}
int bu(node *root,char *s1)
{
    int x,l;
    l=strlen(s1);
    for(int i=0; i<l; i++)
    {
        x=s1[i]-'a';
        if(!root->next[x])
        {
            root->next[x]=init();
        }
        root=root->next[x];
    }
    if(root->flag)
        return root->flag;
    else
    {
        root->flag=++s;
        return s;
    }
}
int fi(int r)
{
   return r==f[r]?r:f[r]=fi(f[r]);
}
void mer(int x,int y)
{
    int a=fi(x);
    int b=fi(y);
    if(a>b)
        f[a]=b;
    else
        f[b]=a;
}
int main()
{
    s=cnt=0;
    node *root;
    root=new node ;
    root=init();
    memset(du,0,sizeof(du));
    for(int i=1; i<=SUM; i++)
        f[i]=i;
    while(gets(now)!=NULL)//注意若是遇到这种输入的方式一定是gets()+sscanf()的形式
    {
        if(!strcmp(now,""))
            break;
        sscanf(now,"%s%s",s1,s2);
        int x=bu(root,s1);
        int y=bu(root,s2);//返回下标的形式,可以很好的描述du的状态,并进行连通图的判断
        du[x]++;
        du[y]++;
        mer(x,y);
    }
    int tmp=0;
    for(int i=1; i<=s; i++)
    {
        if(du[i]%2)
            tmp++;
        if(tmp>2)
        break;
    }
    if(tmp%2||tmp>2)//如果是度==1||度>2则直接输出,不可能
    {
        puts("Impossible");
        return 0;
    }
    bool bj=false;
    for(int i=1;i<=s;i++)
    {
        if(f[i]!=1)//判断是不是连通图,即是否全图都是唯一的跟节点
        {
            bj=true;
            break;
        }
    }
    if(bj)
    {
        puts("Impossible");
        return 0;
    }
    else
        puts("Possible");
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: