洛谷P1127 词链

题目

搜索。并且通过题意所得到的信息先推出几个性质。

如果每个字母在开头的出现次数等于结尾的出现次数,则说明每个单词都有可能要成为起点。

而如果有字母在开头的出现次数比结尾的出现次数大,则只有以该字母为开头的单词才有机会成为起点,这样我们就可以只从他们开始dfs了。

#include <bits/stdc++.h>
#define N 5011
using namespace std;
string s[N];
int n, cnt, flag, top, lin[N], len[N], sum[N], vis[N], sta[N];
struct edg {
 	int to, nex;
}e[1000101];
inline void add(int f, int t)
{
 	e[++cnt].to = t;
 	e[cnt].nex = lin[f];
 	lin[f] = cnt;
}
void dfs(int now)
{
 	vis[now] = 1;
 	sta[++top] = now;
 	for (int i = lin[now]; i; i = e[i].nex)
 	{
 		int to = e[i].to;
 		if (vis[to]) continue;
 		dfs(to);
 	}
 	if (top == n)
 	{
 		cout << s[sta[1]];
 		for (int i = 2; i <= top; i++)
 			cout << "." << s[sta[i]];
 		exit(0);
 	}
 	vis[now] = 0;
 	top--;
}
void check()
{
 	int ha1 = 0, ha_1 = 0;
 	int front = 0;
 	for (int i = 1; i <= 26; i++)
 	{
 		if (sum[i] == 1)
 			front = i, ha1++;//有几个字符串的sum是1 
 		if (sum[i] == -1)//有几个字符串 
 			ha_1++;
 	}
 	if (!ha1 && !ha_1)
 		for (int i = 1; i <= n; i++)
 			dfs(i);
 	else if (ha1 == 1 && ha_1 == 1)
 		for (int i = 1; i <= n; i++)
 			if (s[i][0] - 'a' + 1 == front)
 				dfs(i);
 	//当然,上面情况也不一定满足,因此要到最后输出***. 
	 printf("***");
}
int main()
{
   	scanf("%d", &n);
   	for (int i = 1; i <= n; i++)
   		cin >> s[i];
   	sort(s + 1, s + 1 + n);
   	for (int i = 1; i <= n; i++)
   		len[i] = s[i].size(), sum[s[i][0] - 'a' + 1]++, sum[s[i][len[i] - 1] - 'a' + 1]--;
   	for (int i = 1; i <= n; i++)
   		for( int j = n; j >= 1; j--)
 			if (s[i][len[i] - 1] == s[j][0] && i != j) //保证当前的边一定是从小到大的, 所以要从n到1枚举
   				add(i, j);
   	check();
   	return 0;
}	
/*
6  
aloha
arachnid
dog
gopher
rat
tiger
*/ 
posted @ 2019-10-15 14:18  DAGGGGGGGGGGGG  阅读(229)  评论(0编辑  收藏  举报