昨天周赛H题。。。当时第一发的时候手残了,改正之后发现好像题意不太对,感觉是找最长的一条没有重点的链,又是一张有环的图,不会做,果断放弃去切了另外一个题。之后也没有再读题,也没有分析样例。。。。直到赛后学姐说是找最短路中的最长路,我才发现自己跑偏了。。
也就是说,设P(i,j) 表示 i 到 j 的最短路的长度,则答案为 anw = max( p(i,j) )(i != j)。其实此时 anw 就是图的直径的长度。
其实当时最开始的思路是对的。。。今天按照那个思路写了一遍直接1A了。。当时要是拉着胖胖读一遍题就好了。。
把给出的字符串看成图中对应的结点,则字符串 i 若能通过给出的规则改变且改变一次变成字符串 j ,则说对应的结点i,j有一条边相连。
剩下的就是两次BFS寻找直径的问题了。
对于一个联通的无向图,从任意一点开始BFS,则最后加入队列里的点必为直径的一个端点,然后再从这个端点出发,则最后的那个点即为直径的另一个端点。
但是不知道证明过程。。。这个坑以后再补吧。。。
#include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <stack> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-6) #define LL long long #define ULL unsigned long long int #define _LL __int64 #define _INF 0x3f3f3f3f #define Mod 1000000007 using namespace std; char s[510][51]; int len[510]; bool Match(int u,int v) { if(abs(len[u]-len[v]) >= 2) return false; if(len[u] == len[v]) { int i,ans; for(i = 0,ans = 0;i < len[u]; ++i) { if(s[u][i] != s[v][i]) { ans++; if(ans >= 2) return false; } } } else { if(len[u] > len[v]) swap(u,v); int i,j; for(i = 0,j = 0;i < len[u] && j < len[v];) { if(s[u][i] == s[v][j]) { ++i,++j; } else { ++j; if(abs(i-j) >= 2) return false; } } if(abs(i-j) >= 2) return false; } return true; } struct N { int u,v,next; }edge[250010]; int Top; int head[510]; void Link(int u,int v) { edge[Top].u = u; edge[Top].v = v; edge[Top].next = head[u]; head[u] = Top++; } bool m1[510],m2[510]; int endpoint,TempLength; struct Q { int v,ans; }; void bfs1(int x) { queue<Q> q; Q s,f; s.ans = 1; s.v = x; m1[x] = true; q.push(s); while(q.empty() == false) { f = q.front(); q.pop(); endpoint = f.v; TempLength = f.ans; for(int p = head[f.v];p != -1; p = edge[p].next) { if(m1[edge[p].v] == false) { m1[edge[p].v] = true; s.ans = f.ans+1; s.v = edge[p].v; q.push(s); } } } } void bfs2(int x) { queue<Q> q; Q s,f; s.ans = 1; s.v = x; m2[x] = true; q.push(s); while(q.empty() == false) { f = q.front(); q.pop(); endpoint = f.v; TempLength = f.ans; for(int p = head[f.v];p != -1; p = edge[p].next) { if(m2[edge[p].v] == false) { m2[edge[p].v] = true; s.ans = f.ans+1; s.v = edge[p].v; q.push(s); } } } } int main() { int n,i,j; while(scanf("%d",&n) && n) { for(i = 0;i < n; ++i) { scanf("%*c%s",s[i]); len[i] = strlen(s[i]); } memset(head,-1,sizeof(int)*(n+3)); Top = 0; for(i = 0;i < n; ++i) { for(j = i+1;j < n; ++j) { if(Match(i,j)) { Link(i,j); Link(j,i); } } } memset(m1,false,sizeof(bool)*(n+3)); memset(m2,false,sizeof(bool)*(n+3)); int Max = 1; for(i = 0;i < n; ++i) { if(m1[i] == false) { bfs1(i); bfs2(endpoint); Max = max(Max,TempLength); } } printf("%d\n",Max); } return 0; }