AtCoder Beginner Contest 197 F - Construct a Palindrome

https://atcoder.jp/contests/abc197/tasks/abc197_f

过了一车人的套路我不会。。。

把题目转化成二维平面的模型,dis[u][v]表示从1到u,从n到v,一直走相同字母的距离

然后我们枚举每个点u:{s,e}的所有边,得到u:{s,e}->v:{s.v,e.v}这样的边,且他们走是相同的字母,这样枚举最大是m^2的

然后bfs就可以了,然后枚举中间dis[i][i]*2和dis[i][j]*2+1,i,j,中间有边,答案取最小方案就可以了

注意答案不能直接取dis[1][n]->dis[n][1]

4 4

1 2 b

2 4 a

1 3 a

3 4 b

这样从(1,n)走到(n,1)是一个环,但不是回文串

 

#include<bits/stdc++.h>
using namespace std;

const int maxl=1010;

int n,m,ans;
int dis[maxl][maxl];
struct ed{int v,l;}; 
vector<ed> e[maxl];
struct node{int s,e;};
vector<node> g[maxl][maxl];
char s[10];
bool vis[maxl][maxl];

inline void prework()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);vis[u][v]=vis[v][u]=true;
		scanf("%s",s);
		e[u].push_back(ed{v,s[0]-'0'});
		e[v].push_back(ed{u,s[0]-'0'});
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(ed e1:e[i])
				for(ed e2:e[j])
				if(e1.l==e2.l)
					g[i][j].push_back(node{e1.v,e2.v});
}

inline void mainwork()
{
	memset(dis,0x3f,sizeof(dis));
	dis[1][n]=0;int inf=dis[0][0];
	queue<node> q;q.push(node{1,n});
	while(!q.empty())
	{
		node u=q.front();q.pop();
		for(node v:g[u.s][u.e])
		if(dis[v.s][v.e]==inf)
		{
			dis[v.s][v.e]=dis[u.s][u.e]+1;
			q.push(node{v.s,v.e});
		}
	}
	ans=inf;
	for(int i=1;i<=n;i++)
	{
		ans=min(ans,dis[i][i]*2);
		for(int j=1;j<=n;j++)
		if(vis[i][j])
			ans=min(ans,dis[i][j]*2+1);
	}
}

inline void print()
{
	if(ans==dis[0][0])
		ans=-1;
	printf("%d",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

上一篇:POJ 3280 Cheapest Palindrome(区间dp)


下一篇:【Leetcode】125. 验证回文串(Valid Palindrome)