zoukankan      html  css  js  c++  java
  • POJ-2513 Colored Sticks---欧拉回路+并查集+字典树

    题目链接:

    https://vjudge.net/problem/POJ-2513

    题目大意:

    给一些木棍,两端都有颜色,只有两根对应的端点颜色相同才能相接,问能不能把它们接成一根木棍

    解题思路:

    题意不难,典型的无向图判断是否存在欧拉通路或回路的问题。

    1、欧拉通路或回路的判定条件是图联通,并且度数为奇数的点只有两个或者0个

    2、颜色多,输入的字符串多,需要用字典树存储,给字符串标号用字典树标记

    3、点数多,用并查集判断连通性。

    第一次WA:没由开is_word标记,写成了前缀判断,此处应该是单词判断

    第二次WA:判断连通的时候简单地用p[i] == i;满足该条件的数目等于1来判断连通性,但是此题输入的图可能很复杂,应该判断是否所有点的根节点是同一个点这样进行判断。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<map>
     6 #include<set>
     7 #include<cmath>
     8 #include<algorithm>
     9 #include<vector>
    10 #include<sstream>
    11 #define lowbot(i) (i&(-i))
    12 using namespace std;
    13 
    14 const int maxn = 1e6 + 10;
    15 int tree[maxn][26];
    16 //字典树tree[u][v]表示编号为u的节点的下一个字母为v连接的节点的编号
    17 int idx(char c){ return c - 'a'; }//可以写成宏定义
    18 int tot = 1;//根节点编号为1
    19 bool is_word[maxn];
    20 int sum[maxn];
    21 int cnt = 0;//cnt
    22 int Insert(char s[], int u)//u表示根节点
    23 //插入字符串s
    24 {
    25     for(int i = 0; s[i]; i++)
    26     {
    27         int c = idx(s[i]);
    28         if(!tree[u][c])
    29             tree[u][c] = ++tot;
    30         u = tree[u][c];
    31     }
    32     sum[u] = ++cnt;
    33     is_word[u] = 1;//标记单词结尾
    34     return sum[u];
    35 }
    36 
    37 int ID(char s[], int u)//返回单词s的编号
    38 {
    39     for(int i = 0; s[i]; i++)
    40     {
    41         int c = idx(s[i]);
    42         if(!tree[u][c])//还没有编号
    43             return Insert(s, 1);
    44         u = tree[u][c];
    45     }
    46     if(!is_word[u])//是前缀但是并不是单词
    47     {
    48         return Insert(s, 1);
    49     }
    50     return sum[u];
    51 }
    52 int p[maxn];//并查集
    53 int d[maxn];//记录每个点度数之和
    54 int Find(int x)
    55 {
    56     return x == p[x] ? x : p[x] = Find(p[x]);
    57 }
    58 int main()
    59 {
    60     for(int i = 0; i < maxn; i++)
    61     {
    62         p[i] = i;
    63     }
    64     char s1[15], s2[15];
    65     int u, v, x, y;
    66     while(scanf("%s%s", s1, s2) != EOF)
    67     {
    68         u = ID(s1, 1);
    69         v = ID(s2, 1);
    70         //cout<<u<<" "<<v<<endl;
    71         x = Find(u);
    72         y = Find(v);
    73         if(x != y)p[x] = y;
    74         d[u]++;
    75         d[v]++;
    76     }
    77     int flag = 1, flag1 = 0;
    78     //flag判断连通性
    79     //flag1记录奇点度数的点的数目
    80     int t = Find(1);
    81     if(d[1] & 1)flag1++;
    82     for(int i = 2; i <= cnt; i++)
    83     {
    84         if(Find(i) != t){flag = 0;break;}
    85         if(d[i] & 1)flag1++;
    86     }
    87     if(flag && (flag1 == 0 || flag1 == 2))
    88         printf("Possible
    ");
    89     else printf("Impossible
    ");
    90     return 0;
    91 }
  • 相关阅读:
    超赞!不容错过的5款实用网页开发和设计工具
    如何从平面设计转行到UI设计?
    线段树
    RMQ
    Splay
    Treap
    *模板--矩阵
    最小生成树
    hash
    ac自动机
  • 原文地址:https://www.cnblogs.com/fzl194/p/8951745.html
Copyright © 2011-2022 走看看