poj 2513--Colored Sticks

来源:互联网 发布:淘宝网广场舞服装新款 编辑:程序博客网 时间:2024/06/15 20:49

题意:给出一些列两端带有颜色的不同棍子,问这些棍子首尾相连(当然要颜色相同)是否能形成链状。

解决方案:

  1. 根据输入将棍子当成边,两端颜色为点,构成无向图。
  2. 题目要求计算图中是否存在欧拉路, 存在欧拉路 => 图为连通图且,除了链两端点其他节点的度数皆为偶数。
  3. 若两端节点相同,则度数都为偶,若不同则只存在两个奇数度数节点。同样可证明上述为必要条件,可见图论教材。简单来说,若存在一条最长链W只经过每条边依次,则包括端点的边必定都在链W里,若两端点为同一节点,则此链为局部欧拉环路。因为图连通,则必存在一点可以 到此链,则组成更大一条链。若此链端点不同,则奇数度数顶点都在链中,同样可以加入不在链中的点,因为新加点度数必为偶数,则还可以继续加新点。(证明不充分)。

算法:首先利用数组trie,类似于2503题。不用链表因为初始化指针浪费时间,但是数组大小需要注意。检查通路:首先想到用BFS看是否能从一点到其它任意节点,因为建立邻接表以及BFS浪费时间,需要1s多。

*****初始化个颜色为不同集合,使用并查集,当新加入边时,查找各自根节点,若根节点不同,则把高度 较小的根节点的父节点置为另一根节点,在查找根节点过程中同时路径压缩,时路径中的所有点的父节点都指向根节点。保存边,在所有颜色输入以后再初始化fa数组更快。


#include<cstdio>#include<cstring>using namespace std;#define maxS 26#define maxN 400000#define maxC 500000#define maxM 12struct node{    int colorNo;    int sons[maxS];}trie[maxN];int colorNum;int trieIndex;int edgesNum;int degree[maxC];int fa[maxC];int height[maxC];int edges[250000][2];int trieInsert(char* color){    int now = 0;    int next;    bool IsNewColor = false;    while(*color)    {        next = *color-'a';        if(!trie[now].sons[next])        {            trie[now].sons[next] = ++trieIndex;            IsNewColor = true;        }        now = trie[now].sons[next];        color++;    }    if(IsNewColor)    {        return (trie[now].colorNo = colorNum++);    }    else    {        return trie[now].colorNo;    }}int findSet(int x){    if(x != fa[x])        fa[x] = findSet(fa[x]);           //路径压缩,使路径上的点全部指向x的根节点    return fa[x];}int union_find(){    int i;    for(i = 0;i < colorNum;i++)        fa[i] = i;    for(i = 0;i < edgesNum;i++)    {    int xRoot = findSet(edges[i][0]);    int yRoot = findSet(edges[i][1]);    if(height[yRoot] > height[xRoot])    {        fa[xRoot] = yRoot;    }    else    {        fa[yRoot] = xRoot;        if(height[xRoot] == height[yRoot])            height[xRoot]++;    }    }    return 0;}int trieCheck(char* color,char* color_adj){    int tmpColorNo[2];    tmpColorNo[0] = trieInsert(color);    tmpColorNo[1] = trieInsert(color_adj);    if(tmpColorNo[0] != tmpColorNo[1])    {        degree[tmpColorNo[0]]++;        degree[tmpColorNo[1]]++;        edges[edgesNum][0] = tmpColorNo[0];        edges[edgesNum++][1] = tmpColorNo[1];    }    return 0;}bool judge(){    int i;    int oddNum = 0;    for(i = 0;i < colorNum;i++)    {        if(fa[i] != fa[0])            return false;        if(degree[i]%2)        {            oddNum++;            if(oddNum > 2)                return false;        }    }    return true;}int main(){    char colorTmp1[maxM],colorTmp2[maxM];    trieIndex = 0;    colorNum = 0;    edgesNum = 0;    while(~scanf("%s%s",colorTmp1,colorTmp2))    {        trieCheck(colorTmp1,colorTmp2);    }    union_find();    if(!colorNum||judge())     //此题有零输入情况    {        printf("Possible\n");    }    else    {        printf("Impossible\n");    }    return 0;}


0 0
原创粉丝点击