首页 > 其他分享 >POJ 2337 Catenyms (欧拉回路+并查集)

POJ 2337 Catenyms (欧拉回路+并查集)

时间:2023-04-13 23:39:44浏览次数:47  
标签:bin head 30 2337 int 查集 edge POJ include


题目地址:POJ 2337

这题跟POJ 1386差不多,只不过这题多一个输出路径而已。

按字母来建边,每个单词的首字母和尾字母加边。先判断是否连通,然后判断每个字母的入度和出度不能出现差的绝对值大于2,然后入度和出度差的绝对值为1的不能超过两个。就可以形成欧拉路径

代码如下:


#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL long long
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
int head[30], cnt, in[30], out[30], bin[30], path[1100], top, vis[1100], ha[30], c[30];
int find1(int x)
{
        return bin[x]==x?x:bin[x]=find1(bin[x]);
}
void join(int x, int y)
{
        int f1=find1(bin[x]);
        int f2=find1(bin[y]);
        if(f1!=f2){
                bin[f2]=f1;
        }
}
struct N
{
        char s[30];
}fei[1100];
bool cmp(N f1, N f2)
{
        return strcmp(f1.s,f2.s)>0;
}
struct node
{
        int u, v, id, next;
}edge[1100];
void add(int u, int v, int id)
{
        edge[cnt].v=v;
        edge[cnt].id=id;
        edge[cnt].next=head[u];
        head[u]=cnt++;
}
void dfs(int u)
{
        for(int i=head[u];i!=-1;i=edge[i].next){
                if(!vis[edge[i].id]){
                        vis[edge[i].id]=1;
                        head[u]=i;
                        dfs(edge[i].v);
                        path[top++]=edge[i].id;
                }
                i=head[u];
        }
}
void init()
{
        memset(head,-1,sizeof(head));
        cnt=top=0;
        memset(vis,0,sizeof(vis));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(ha,0,sizeof(ha));
}
int main()
{
        int t, n, i, j, len, k, sum, flag, x, pos;
        scanf("%d",&t);
        while(t--){
                scanf("%d",&n);
                init();
                for(i=0;i<n;i++){
                        scanf("%s",fei[i].s);
                }
                sort(fei,fei+n,cmp);
                k=0;
                for(i=0;i<26;i++){
                        bin[i]=i;
                }
                for(i=0;i<n;i++){
                        len=strlen(fei[i].s);
                        in[fei[i].s[len-1]-'a']++;
                        out[fei[i].s[0]-'a']++;
                        if(!ha[fei[i].s[0]-'a']){
                                ha[fei[i].s[0]-'a']=1;
                                c[k++]=fei[i].s[0]-'a';
                        }
                        if(!ha[fei[i].s[len-1]-'a']){
                                ha[fei[i].s[len-1]-'a']=1;
                                c[k++]=fei[i].s[len-1]-'a';
                        }
                        add(fei[i].s[0]-'a',fei[i].s[len-1]-'a',i);
                        join(fei[i].s[0]-'a',fei[i].s[len-1]-'a');
                }
                //printf("k===%d\n",k);
                sum=flag=0;
                x=find1(bin[c[0]]);
                for(i=0;i<k;i++){
                        if(abs(in[c[i]]-out[c[i]])>1) flag=1;
                        if(in[c[i]]!=out[c[i]]) sum++;
                        if(find1(bin[c[i]])!=x) flag=1;
                }
                if(flag||sum>2){
                        puts("***");
                        continue ;
                }
                sort(c,c+k);
                pos=c[0];
                for(i=0;i<k;i++){
                        if(out[c[i]]>in[c[i]]){
                                pos=c[i];
                                break;
                        }
                }
                dfs(pos);
                for(i=top-1;i>=0;i--){
                        printf("%s",fei[path[i]].s);
                        if(i) printf(".");
                }
                puts("");
        }
        return 0;
}



标签:bin,head,30,2337,int,查集,edge,POJ,include
From: https://blog.51cto.com/u_16070138/6188693

相关文章

  • POJ 1905 Expanding Rods (二分+计算几何+精度处理)
    题目地址:POJ1905用二分枚举h,然后判断弧长是否符合条件。重点还是在精度问题上,具体看代码吧。。#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib.h>#include<map>#include<set>#include......
  • POJ 2299 Ultra-QuickSort(线段树+离散化)
    题目地址:POJ2299这题曾经用归并排序做过,线段树加上离散化也可以做。一般线段树的话会超时。这题的数字最大到10^10次方,显然太大,但是可以利用下标,下标总共只有50w。可以从数字大的开始向树上加点,然后统计下标比它小即在它左边的数的个数。因为每加一个数的时候,比该数大的数已经加完......
  • POJ 3468 A Simple Problem with Integers(线段树区间更新)
    题目地址:POJ3468打了个篮球回来果然神经有点冲动。。无脑的狂交了8次WA。。居然是更新的时候把r-l写成了l-r。。。这题就是区间更新裸题。区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新。其他的均按线段树的来就行。代码如下:#include<iostream>#in......
  • POJ 1226 Substrings (后缀数组)
    题目地址:POJ1226将每一个字符串反转连接一次,再把所有字符串都连接起来,然后二分,找最大长度。注意与反转字符串之间不能直接相连。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib.h>#include<ma......
  • POJ 2774 Long Long Message (后缀数组)
    题目地址:POJ2774后缀数组第一发!后缀数组真是太神奇了。。(好像每学一种新算法我都会这么说。。原理研究了好长时间,还有代码的实现,论文作者罗穗骞的代码太简洁。。好难看懂QAQ,看了好长时间。来一发后缀数组模板题,模板是用的倍增思想。代码如下:#include<iostream>#include......
  • POJ 1987 Distance Statistics (树上点分治)
    题目地址:POJ1987点分治模板题,跟POJ1741几乎一样,。。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm>#include<stdlib.h>#include<map>#include<set>#include<std......
  • SPOJ 1825 FTOUR2 - Free tour II (树上点分治)
    题目地址:SPOJ1825树分治的题果然除了模板题就是金牌题啊。。。这题是一道论文题,想了好长时间。。。。终于过了,,,,注意一个坑点,如果权值全部为负的话,是可以不选任意一条边的,这样权值为0。。。也就是说初始值要设为0。。。具体看漆子超的论文《分治算法在树的路径问题中的应用》......
  • SPOJ 705 New Distinct Substrings (后缀数组)
    后缀数组模板题。由于height数组是指与排名上一个的公共前缀,所以重复的个数是height[i]个,考虑当前这个字母所构成的子串的贡献即为n-sa[i]-height[i],然后累加即可。代码如下:#include<iostream>#include<string.h>#include<math.h>#include<queue>#include<algorithm......
  • SPOJ 375 QTREE系列-Query on a tree (树链剖分)
    题目地址:SPOJ375树链剖分第一发!果然是个貌似很高级的数据结构,其实就是把树的边从树形结构转化成了线性结构,从而可以用线段树或树状数组之类的数据结构进行快速维护。从而将时间缩到n*log(2*n).这题用的线段树维护的。代码如下:#include<iostream>#include<string.h......
  • POJ 3237 Tree (树链剖分)
    题目地址:POJ3237这题用了一下午。。本来一直认为max和min两个数组是不用改的,只需要改lazy数组,然后在查询的时候利用lazy标记来返回max或-min,后来发现错的很严重。。这题要在pushdown中修改max和min数组,从而实现最大值取反。代码如下:#include<iostream>#include<strin......