洛谷:P1127 词链(图,提高+/省选-)

题目:

分析:这个题放这里我当然会做了。直接进行状态转化,单词转化为点,构造一个有向的图。

单词要先排序。

然后问题转化为在图中寻找能走完全部的最小路径了。

具体怎么找呢?应该首先从0开始,能遍历的都标记,然后从没标记的中找最小的,遍历看看没标记的是否可以全部标记了,以此类推,???半个月后看到自己瞎写真无语。

代码:

只优化了:排序后从最小的开始。

#include<bits/stdc++.h>
using namespace std;
int m;
vector<string> vs;//点从0开始编号
vector<vector<int> > vvb;//以什么为开头的 
vector<vector<int> > vve;//以什么为结尾的 
int done[1050];
bool dfs(int x,int num,vector<string> &v)
{
 if(num==vs.size()) 
 {
  return 1;
 }
 char ee=vs[x][vs[x].size()-1];
 for(int i=0;i<vvb[ee-'a'].size();i++)
 {
  if(done[vvb[ee-'a'][i]]==1) continue;
  vector<string> vv=v;
  v.push_back(vs[vvb[ee-'a'][i]]);
  done[vvb[ee-'a'][i]]=1;
  if(dfs(vvb[ee-'a'][i],num+1,v)) return 1;
  v=vv;
  done[vvb[ee-'a'][i]]=0;
 }
 return 0;
}
int main()
{
 cin>>m;
 vector<int> v;
 for(int i=0;i<26;i++)
 {
  vvb.push_back(v);
 }
 for(int i=0;i<m;i++)
 {
  string ss;
  cin>>ss;
  vs.push_back(ss);
 }
 sort(vs.begin(),vs.end());
 for(int i=0;i<m;i++)
 {
  char bb=vs[i][0];
  vvb[bb-'a'].push_back(i);
 }
 memset(done,0,sizeof(done));
 int begin=-1;
 vector<string> vs22;
 for(int i=0;i<m;i++)
 {
  done[i]=1;
  if(dfs(i,1,vs22)) {
   begin=i; break;
  };
  done[i]=0;
 }
 if(begin==-1) {
  cout<<"***";
  return 0;
 }
 cout<<vs[begin];
 done[begin]=1;
 for(int i=0;i<vs22.size();i++) cout<<'.'<<vs22[i];
}

在这里插入图片描述

优化,入度为0的点,最多有两个。

没有的话,再用上面的方法。

挺简单的代码写了好长时间了,懒得搞了。

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/108029938