POJ 2337 Catenyms 欧拉通路

题目链接:点击打开链接

题意:

把输入的n个由小写字母构成的字符串连成字典序最小的一句话,使得所有字符串都恰好出现一次且相邻两个字符串相邻的字母相同

思路:

比如abcd,我们认为是这样一条边:a->d

所以我们在a->d间建一条边。

1、如:abcd, dfgh,

那么得到的边就是 a->d, d->h。

而题目的目标是每个字符串恰好用一次,即每条边恰好用一次。也就是找一条欧拉通路

2、我们只需要关心字符串的首尾2个字母,所以我们认为图里只有26个节点。

3、判断欧拉通路是否存在:

保证图是连通的。

保证图里要么(每个点入度=出度,此时路径的起点任意)要么(恰好一个点入度为1,同时恰好一个点出度为1,此时路径的起点只能为出度为1的点)

4、寻找欧拉通路:

因为(3)中已经保证欧拉通路存在,则我们随便找一条就可以了

dfs时顺便记录经过的边(注意记录的是边而不是点)

输出路径时把记录的边逆序输出即可。

import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Queue;

public class Main {
	class Node implements Comparable<Node>{
		int v, vis;
		String str;
		Node(){}
		Node(int v, int vis, String str){
			this.v = v;
			this.vis = vis;
			this.str = str;
		}
		public int compareTo(Node o) {
			return this.str.compareTo(o.str);
		}
	}
	int n;
	ArrayList<Node>[] G = new ArrayList[Maxn];
	Stack<String> stack = new Stack();
	int[] vis = new int[Maxn], f = new int[Maxn], In = new int[Maxn], Out = new int[Maxn];
	int find(int x){return (x==f[x])?x:(f[x]=find(f[x]));}
	void Union(int x, int y){
		int fx = find(x), fy = find(y);
		if(fx == fy)return ;
		f[fx] = fy;
	}
	void find_path(int u){
		for (int i = 0; i<G[u].size(); i++)
		{
			int v = G[u].get(i).v;
			if (0 == G[u].get(i).vis)
			{
				G[u].get(i).vis = 1;
				find_path(v);
				stack.push(G[u].get(i).str);
			}
		}
	}
	void print(){
		out.print(stack.pop());
		while(!stack.isEmpty())
			out.print("."+stack.pop());
		out.println();
	}
	int id;//id为起点编号
	boolean euler_formula(){
		int cnt_big = 0, cnt_less = 0; id = -1;
		for (int i = 0; i<26; i++)
			if (vis[i] == 1)
			{
				if (In[i] == Out[i])continue;
				if (In[i] - Out[i] == 1)cnt_big++;
				else if (In[i] - Out[i] == -1){cnt_less++; id = i;}
				else return false;
			}

		if (false == (cnt_big == 1 && cnt_less == 1) && false == (cnt_big == 0 && cnt_less == 0))return false;
		int cnt = 0; //图的联通块个数必须为1
		for(int i = 0; i < Maxn; i++)
			if(vis[i] == 1 && f[i] == i)cnt++;
		return cnt == 1;
	}
	void add(int u, int v, String str){
		Out[u] ++; In[v] ++;
		vis[u] = vis[v] = 1;
		Node E = new Node(v, 0, str);
		G[u].add(E);
		Union(u, v);
	}
	void init(){
		for(int i = 0; i < Maxn; i++){
			f[i] = i;
			vis[i] = In[i] = Out[i] = 0;
			G[i].clear();
		}
		stack.clear();
	}
	void input(){
		init();
		n = cin.nextInt();
		for(int i = 1; i <= n; i++)
		{
			String s = "";
			while(s.length()==0 || s.charAt(0)<'a'||s.charAt(0)>'z')s = cin.next();
			int u = s.charAt(0)-'a', v = s.charAt(s.length()-1)-'a';
			add(u, v, s);
		}
		for(int i = 0; i < Maxn; i++) Collections.sort(G[i]); //排序保证字典序最小
	}
	void work() {
		for(int i = 0; i < Maxn; i++) G[i] = new ArrayList();
		int T = cin.nextInt();
		while(T-->0){
			input();
			if(euler_formula()){
				if(id == -1)
					for(int i = 0; i < 26 && id == -1; i++)
						if(vis[i] == 1)
							 id = i;//若每个点出度=入度则起点任取
				find_path(id);
				print();
			}
			else out.println("***");
		}
	}

	Main() {
		cin = new Scanner(System.in);
		out = new PrintWriter(System.out);
	}

	public static void main(String[] args) {
		Main e = new Main();
		e.work();
		out.close();
	}

	public Scanner cin;
	public static PrintWriter out;
	static int Maxn = 26;
}
时间: 2024-10-12 04:01:11

POJ 2337 Catenyms 欧拉通路的相关文章

POJ 2337 Catenyms (有向图欧拉通路)

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9914   Accepted: 2588 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For e

[ACM] POJ 2513 Colored Sticks (Trie树,欧拉通路,并查集)

Colored Sticks Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 29736   Accepted: 7843 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 st

POJ训练计划_Colored Sticks(字典树+判断欧拉通路)

解题报告 http://blog.csdn.net/juncoder/article/details/38236333 题目传送门 题意: 问给定一堆的棒,两端有颜色,相同的颜色的棒可以头尾相接,能否连在一条直线. 思路: 把每一根棒两端看成两个点,之间连着线,判断这样的一个图中是否有欧拉通路 欧拉通路: 在联通无向图中,经过G的每一条边一次并且仅有一次的路径为欧拉通路. 求欧拉通路的充分条件:图为联通图,并且仅有两个奇度数的结点或无奇度结点. #include <queue> #includ

POJ 1780 Code(欧拉通路)

输入n(1<=n<=6),输出长度为10^n + n -1 的字符串答案. 其中,字符串以每n个为一组,使得所有组都互不相同,且输出的字符串要求字典序最小. 显然a[01...(n-1)]和a[12...n]为相邻组,可以看做有一条边从结点a[01...(n-1)]到结点a[12...n]. 题目转化成求欧拉通路.如果以每组的值为结点,则有10^6个结点,10^7条边.会MLE.(此时其实是哈密顿通路?) 这里以每组的值为边的边权,而边的2个结点分别是前n-1位数和后n-1位数.这样点是10^

POJ--1300--Door Man【推断无向图欧拉通路】

链接:http://poj.org/problem?id=1300 题意:有n个房间.每一个房间有若干个门和别的房间相连.管家从m房间開始走.要回到自己的住处(0),问是否有一条路能够走遍全部的门而且没有反复的路. 无向图欧拉通路充要条件:G为连通图,而且G仅有两个奇度结点(度数为奇数的顶点)或者无奇度结点. 无向图欧拉回路充要条件:G为无奇度结点的连通图. 思路:推断是否存在欧拉通路.依据欧拉通路.欧拉回路的性质来做.有两种情况:一种是欧拉回路.全部房间的门的个数都是偶数个,而且此时初始房间不

poj 2337(单向欧拉路的判断以及输出)

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11648   Accepted: 3036 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For

POJ--1300--Door Man【判断欧拉通路】

链接:http://poj.org/problem?id=1300 题意:有n个房间,每个房间有若干个门和别的房间相连,管家从m房间开始走,要回到自己的住处(0),问是否有一条路可以走遍所有的门并且没有重复的路. 思路:判断是否存在欧拉通路,根据欧拉通路.欧拉回路的性质来做.有两种情况:一种是欧拉回路,所有房间的门的个数都是偶数个,并且此时初始房间不是0,此时存在要求的路径,如果初始是0则不行.另一种是欧拉通路,只有两个房间门是奇数个,剩下都是偶数个,并且这两个房间一个是0,一个是当前起点,并且

FZU 2112 并查集、欧拉通路

原题:http://acm.fzu.edu.cn/problem.php?pid=2112 首先是,票上没有提到的点是不需要去的. 然后我们先考虑这个图有几个联通分量,我们可以用一个并查集来维护,假设有n个联通分量,我们就需要n-1条边把他们连起来. 最后对于每个联通分量来说,我们要使它能一次走完,就是要求他是否满足欧拉通路,也就是这个联通分量中至多有2个度为奇数的点,每多出2个度为奇数的点,就多需要一条边(因为单个连通分量的所有点的度数之和为偶数,所以不可能存在奇数个奇数度数的点). 1 #i

hdu 1116 Play on Words(欧拉通路)

Problem Description Some of the secret doors contain a very interesting word puzzle. The team of archaeologists has to solve it to open that doors. Because there is no other way to open the doors, the puzzle is very important for us. There is a large