zoj 1919 poj 2337 Catenyms(欧拉路径求解)

2024-06-15 19:38

本文主要是介绍zoj 1919 poj 2337 Catenyms(欧拉路径求解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

zoj 1919 poj 2337  Catenyms

前一个单词的尾字母与后一个单词的第一个字母相同 

输出字典序最小的序列


用向量数组e[i]来存储以i开头的字符串  由于要是按字典序输出 所以需要讲字符串排序

f[i][j]数组表示 以第i个字母开头的第j个单词有没有被选取

level记录递归的层数  到达n之后 所有单词被选取 结束

yes标记有木有找到 找到了之后 递归  循环都结束

其他的基本都是模版的东西  并查集判断是不是连通

判断能不能形成欧拉图 根据度数情况选取dfs的起点

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>#define eps 1e-8
#define op operator
#define MOD  10009
#define MAXN  1010
#define INF 0x7fffffff
#define MEM(a,x)    memset(a,x,sizeof a)
#define ll __int64
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;int n;
int rd[30],cd[30];
int par[30];
vector<string> e[30],ans;
int f[30][1010],w[30][1010];
int yes,level;
int num;struct edge
{int u,v;
};
edge ed[1000100];void init()
{for(int i=0;i<26;i++)par[i]=-1;
}int Find(int x)
{int s;for(s=x;par[s]>=0;s=par[s]);while(s!=x){int tmp=par[x];par[x]=s;x=tmp;}return s;
}void Union(int R1,int R2)
{int r1=Find(R1),r2=Find(R2);int tmp=par[r1]+par[r2];if(par[r1]>par[r2]){par[r1]=r2;par[r2]=tmp;}else{par[r2]=r1;par[r1]=tmp;}
}bool conn()
{
//    init();for(int i=0;i<num;i++){int u=ed[i].u,v=ed[i].v;if(u!=v&&Find(u)!=Find(v))Union(u,v);}int fir=-1;for(int i=0;i<26;i++){if(rd[i]+cd[i]==0)continue;if(fir==-1) fir=i;else if(Find(i)!=Find(fir))return 0;}return 1;
}void dfs(int x)
{
//    cout<<"666"<<endl;if(level==n)  {yes=1; return; }int i;for(i=cd[x]-1;i>=0;i--)//从小到大寻找可行路径{int y=w[x][i];if(!f[x][i])//以a开头的第i个串  没有被用过{level++; f[x][i]=1;dfs(y);level--; f[x][i]=0;}if(yes)  break;}if(yes) ans.push_back(e[x][i]);
}int main()
{
//freopen("ceshi.txt","r",stdin);int tc;scanf("%d",&tc);while(tc--){init();MEM(rd,0); MEM(cd,0); MEM(f,0); MEM(w,0);for(int i=0;i<30;i++)e[i].clear();ans.clear();num=0;scanf("%d",&n);getchar();char s[40];for(int i=0;i<n;i++){scanf("%s",s);string str=s;
//            cin>>str;int u=str[0]-'a';e[u].push_back(str);cd[u]++;}for(int i=0;i<26;i++){sort(e[i].begin(),e[i].end());reverse(e[i].begin(),e[i].end());}for(int i=0;i<26;i++){
//            cout<<"cd  "<<cd[i]<<endl;for(int j=0;j<cd[i];j++){int len=e[i][j].length();int v=e[i][j][len-1]-'a';rd[v]++;int u=e[i][j][0]-'a';
//                Union(u,v);ed[num].u=u; ed[num].v=v;num++;w[i][j]=v;//以i开头 从大到小排序之后 第j个串的尾字母是v}}
//        cout<<"666"<<endl;int flag=1;int start=-1;int cr=0,rc=0;for(int i=0;i<26;i++){if(rd[i]-cd[i]>=2||cd[i]-rd[i]>=2){flag=0; break;}if(rd[i]-cd[i]==1){rc++;if(rc>1){flag=0; break;}}if(cd[i]-rd[i]==1){cr++;start=i;if(cr>1){flag=0; break;}}}if(rc!=cr) flag=0;if(!conn())  flag=0;yes=0; level=0;if(!flag)puts("***");else{if(start>=0){dfs(start);
//                reverse(ans.begin(),ans.end());}else{for(int i=0;i<26&&!yes;i++){level=0;if(cd[i])dfs(i);}}reverse(ans.begin(),ans.end());for(int i=0;i<n-1;i++)cout<<ans[i]<<".";cout<<ans[n-1]<<endl;}}return 0;
}



这篇关于zoj 1919 poj 2337 Catenyms(欧拉路径求解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1064386

相关文章

随想录 Day 69 并查集 107. 寻找存在的路径

随想录 Day 69 并查集 107. 寻找存在的路径 理论基础 int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好vector<int> father = vector<int> (n, 0); // C++里的一种数组结构// 并查集初始化void init() {for (int i = 0; i < n; ++i) {father[i] = i;}

SQL Server中,用Restore DataBase把数据库还原到指定的路径

restore database 数据库名 from disk='备份文件路径' with move '数据库文件名' to '数据库文件放置路径', move '日志文件名' to '日志文件存放置路径' Go 如: restore database EaseWe from disk='H:\EaseWe.bak' with move 'Ease

C# 命名管道中客户端访问服务器时,出现“对路径的访问被拒绝”

先还原一下我出现错误的情景:我用C#控制台写了一个命名管道服务器,然后用ASP.NET写了一个客户端访问服务器,运行之后出现了下面的错误: 原因:服务器端的访问权限不够,所以是服务器端的问题,需要增加访问权限。(网上很多都说是文件夹的权限不够,情况不同,不适用于我这种情况) 解决办法: (1)在服务器端相应地方添加以下代码。 PipeSecurity pse = new PipeSec

代码随想录算法训练营第三十九天|62.不同路径 63. 不同路径 II 343.整数拆分 96.不同的二叉搜索树

LeetCode 62.不同路径 题目链接:62.不同路径 踩坑:二维的vector数组需要初始化,否则会报错访问空指针 思路: 确定动态数组的含义:dp[i][j]:到达(i,j)有多少条路经递推公式:dp[i][j] = dp[i-1][j] + dp[i][j-1]初始化动态数组:dp[0][0] = 1遍历顺序:从左到右,从上到下 代码: class Solution {pu

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符。然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string

poj 3294(Life Forms) 2分+ 后缀数组

我曾用字符串hash写,但是超时了。只能用后最数组了。大致思路:用不同的符号吧字符串连接起来,构建后缀数组,然后2分答案,依次扫描后缀数组,看是否瞒住条件。 VIEW CODE #include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<cstring>#include<cassert>#

poj 2391 Ombrophobic Bovines (网络流)

这是一道很经典的网络流的题目。首先我们考虑假如我们的时间为无穷大。我们吧每个点拆成2个点 i和i' .。虚拟源点s和汇点t。对于每个点建边(s,i, a[i])  (i‘,t,ib[i]) 。 其中a[i]为给点有多少牛,b[i]为容量。i和j连通 建边 (i,j',inf);如果最大流==所有牛的个数,就可能装下所有的牛。那么现在我们考虑时间。假设最大时间为T.那么如果i到j的的最短时间>T

poj 1330 LCA 最近公共祖先

水题目。直接上代码了。 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string>#include<cstring>#include<map>#include<vector>#

poj 3160 Father Christmas flymouse 强连通+dp

首先我们可以确定的是,对于val值小于0的节点都变成0.   假设一个集合内2个房间都能任意到达,那么我就可以吧集合内的所有点的价值都取到,并且可以达到任一点。实际上集合内的每个点是相同的,这样的集合就是一个强连通分量。 那么我们就可以用tarjin算法进行强连通缩点, 最后形成一个dag的图。在dag的图上面进行dp。可以先用拓扑排序后dp。或者建反响边记忆化搜索 。 VIEW