SDUT 2838 Word ladder 图的直径

昨天周赛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;
}

你可能感兴趣的:(SDUT 2838 Word ladder 图的直径)