问题 C(2419): 百进制数
时间限制: 1 Sec 内存限制: 128 MB
题目描述
科学进步飞快,日新月异,人们早已经不再习惯十进制那种单调的表示数字的方式。最近,Y同学投入百进制数的研究中。两个百进制数可以相邻当且仅当前一个百进制数的最后一位和后一个百进制数的第一位相同,这一位数字称之为一个交点,每一位数字最多能以起点和终点的角色属于交点一次(例如1234—3434—3412,是非法序列,因为34以起点和终点的角色充当交点各两次)。任意一个百进制数或多个可以相邻的百进制数可以形成一个合法序列。一个完美序列满足序列中所有的百进制数长度之和是所有合法序列中最大的。给出n个百进制数,我们希望将其排列才能组成最长的百进制数完美序列。
输入
第一行一个数n表示百进制数的个数;
第二行到第n−1行每行一个长度为L的百进制数。
输出
输出完美序列的长度。
样例输入
5
1234
347891
1291
9988
9156
样例输出
14
提示
20%的数据:1≤n≤10,1≤L≤10;
80%的数据:1≤n≤50,1≤L≤100;
100%的数据:1≤n≤100,1≤L≤100;
其实这道题蛮简单的只需要以1~99为点,数字串为边,然后SPFA跑最长路就行了,唯一需要处理的就是百进制数的第一位和最后一位的转换,以及起点和终点不算交点,可以经过两次。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define MAXN 100
#define MAXM 100
#define INF 0x3f3f3f3f
typedef long long int LL;
struct node
{
int v,w;
node *next;
}*adj[MAXN+10],Edges[MAXM+10],*New=Edges;
void addedge(int u,int v,int w)
{
node *p=++New;
p->v=v;
p->w=w;
p->next=adj[u];
adj[u]=p;
}
int N;
bool vis[MAXN+10];
int dfs(int x)
{
int rn=0;
for(node *p=adj[x];p!=NULL;p=p->next)
{
if(!vis[p->v])
{
vis[p->v]=1;
rn=max(rn,dfs(p->v)+p->w);
vis[p->v]=0;
}
else rn=max(rn,p->w);
}
return rn;
}
int main()
{
scanf("%d",&N);
int i,j;
char str[110];
int len;
for(i=1;i<=N;++i)
{
scanf("%s",str+1);
len=strlen(str+1);
if(len&1)addedge((str[1]-'0'),(str[len-1]-'0')*10+(str[len]-'0'),len);
else addedge((str[1]-'0')*10+(str[2]-'0'),(str[len-1]-'0')*10+(str[len]-'0'),len);
}
int ans=0;
for(i=1;i<=99;++i)
ans=max(ans,dfs(i));
printf("%d\n",ans);
}