Codeforces 666B. World Tour 解题报告

传送门
题意:一个有N个定点M条边的有向图,dist[i][j]表示从i到j的最短距离,每条边的长度皆为1,请你给出有序的四个点a,b,c,d,使dist[a][b]+dist[b][c]+dist[c][d]最大。


思路:先用SPFA处理最短路是显然的,然后就是怎么选择点的问题,既然要和最大,那么肯定是两两个点之间的距离最大,那么我们可以预处理出每个点距离最远的点,然后只暴力中间两个点,注意预处理的时候不能用set以求方便,set常数较大会超时,还要注意不能只处理距离最远的,因为会有重复的情况,还要注意重复的情况挪点的时候,要判断size是否大于1,否则会越界。


AC程序

//库省略
using namespace std;
const int maxn=3005,INF=1e9;
int n,m;
vector<int> g[maxn];
bool vis[maxn];
int dis[maxn][maxn];
int far[maxn],len[maxn];
pii to[maxn][5],back[maxn][5];
void SPFA()
{
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        dis[i][i]=0;
        queue<int> q;
        q.push(i);
        while(!q.empty())
        {
            int u=q.front();
            vis[u]=1;
            q.pop();
            for(int j=0;jint v=g[u][j];
                dis[i][v]=min(dis[i][v],dis[i][u]+1);
                if(!vis[v])
                q.push(v);
            }
        }
    }
}
bool cmp(pii a,pii b)
{
    return a.fi>b.fi;
}
void updateto(int x,int len,int id)
{
    to[x][3].fi=len;
    to[x][3].se=id;
    sort(to[x],to[x]+4,cmp);
}
void updateback(int x,int len,int id)
{
    back[x][3].fi=len;
    back[x][3].se=id;
    sort(back[x],back[x]+4,cmp);
}
int main()
{
    cin>>n>>m;
    for(int i=0;iint x,y;
        cin>>x>>y;
        g[x].pb(y);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            dis[i][j]=INF;
        }
    }
    memset(len,-1,sizeof(len));
    SPFA();
    /*
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j || dis[i][j]==INF)
            continue;
            updateto(i,dis[i][j],j);
            updateback(j,dis[i][j],i);
        }
    }
    /*
    for(int i=1;i<=n;i++)
    {
        cout<
    int maxm=-1;
    int a1=0,a2=0,a3=0,a4=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j || dis[i][j]==INF || !to[j][0].se || !back[i][0].se)
            continue;
            //cout<
            int ans1,ans2;
            int nex=0,bac=0;
            int nexid=to[j][nex].se,bacid=back[i][bac].se;
            //cout<

            if(nexid==i)
            nex++;
            if(bacid==j)
            bac++;
            if(!to[j][nex].se || !back[i][bac].se)
            continue;
            nexid=to[j][nex].se;
            bacid=back[i][bac].se;
            int nexlen=to[j][nex].fi,baclen=back[i][bac].fi;

            if(nexid==bacid)
            {
                bac++;nex++;
                nexid=to[j][nex].se;
                bacid=back[i][bac].se;
                if(nexid==0 && bacid==0)
                continue;
                if(nexid!=0 && bacid!=0)
                {
                    bac--;
                    nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                    ans1=nexlen+baclen;//nex


                    bac++;nex--;
                    nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                    ans2=nexlen+baclen;//bac


                    if(ans1>ans2)
                    bac--,nex++;
                    nexid=to[j][nex].se;
                    bacid=back[i][bac].se;
                }
                else
                {
                    if(nexid==0)
                    nex--;
                    else
                    bac--;
                    nexlen=to[j][nex].fi;baclen=back[i][bac].fi;
                    nexid=to[j][nex].se;bacid=back[i][bac].se;
                    ans2=ans1=nexlen+baclen;
                }
            }
            ans2=ans1=nexlen+baclen;
            ans1+=dis[i][j];
            ans2+=dis[i][j];
            int ans=max(ans1,ans2);
            //cout<
            if(ans>maxm)
            {
                maxm=ans;
                a1=bacid;
                a2=i;
                a3=j;
                a4=nexid;
            }
        }
    }
    cout<" "<" "<" "<return 0;
}

你可能感兴趣的:(codeforces)