2019.03.23【NOIP提高组】模拟 A 组

本文提供了CF666B World Tour等题目的详细解题思路与代码实现,重点介绍了如何通过SPFA算法寻找特定条件下最短路径的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JZOJ 4671 CF666B World Tour

题目

一张 n n n个点 m m m条边的有向图,每条边的权值相同.你要找4个点 a , b , c , d a,b,c,d a,b,c,d,使得 a − > b − > c − > d a->b->c->d a>b>c>d的最短路最长( a , b , c , d a,b,c,d a,b,c,d之间要有路),输出一组解.


分析

枚举 b , c b,c b,c,找到最适合的 a , d a,d a,d,求出它们的最短路径
首先要跑 n n n遍spfa,然后找到对于每个点来说最适合的两个点,也就是最短路径大到小排序的最靠前的两个点,


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <deque>
#define rr register
#define r(i,a,b) for (rr int i=a;i<=b;++i)
using namespace std;
struct node{int y,next;}e[5001];
int t[3011],a[3001][2],b[3001][2],ls[3001];
int dis[3001][3001],n,ans,m,ans1,ans2,ans3,ans4;
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void spfa(int s){
    rr deque<int>q; rr bool v[3001];
    memset(v,0,sizeof(v)); memset(dis[s],127/3,sizeof(dis[s]));
    dis[s][s]=0; q.push_front(s); v[s]=1;
    while (q.size()){
        rr int x=q.front(); q.pop_front();
        for (rr int i=ls[x];i;i=e[i].next)
        if (dis[s][e[i].y]>dis[s][x]+1){
            dis[s][e[i].y]=dis[s][x]+1;
            if (!v[e[i].y]){
                v[e[i].y]=1;
                if (q.size()&&dis[s][e[i].y]<dis[s][q.front()]) q.push_front(e[i].y);
                    else q.push_back(e[i].y);
            }
        }
        v[x]=0;
    }
}
inline signed run(){
    rr int ans=n+1;
    r(i,1,n) if (t[ans]<t[i]) ans=i;
    if (ans<=n) t[ans]=-707406378;
        else ans=-1;
    return ans;
}
signed main(){
    n=iut(); m=iut();
    memset(a,-1,sizeof(a));
    memset(b,-1,sizeof(b));
    r(i,1,m){
        rr int x=iut();
        e[i]=(node){iut(),ls[x]}; ls[x]=i;
    }
    r(i,1,n){
    	spfa(i);
    	r(j,1,n)
            if (dis[i][j]==707406378)
                dis[i][j]=-1;
    }
   r(i,1,n){
        r(j,1,n) t[j]=dis[i][j]; r(j,0,1) a[i][j]=run();
        r(j,1,n) t[j]=dis[j][i]; r(j,0,1) b[i][j]=run();
    }
    r(i,1,n) r(j,1,n) if (i!=j&&dis[i][j]!=-1)
    r(t1,0,1) if (b[i][t1]!=-1&&b[i][t1]!=j){
        rr int now=b[i][t1];
        r(t2,0,1) if (a[j][t2]!=-1&&a[j][t2]!=i&&a[j][t2]!=now)
        if (ans<dis[now][i]+dis[i][j]+dis[j][a[j][t2]])
            ans=dis[now][i]+dis[i][j]+dis[j][a[j][t2]],
            ans1=now,ans2=i,ans3=j,ans4=a[j][t2];
    }
    return !printf("%d %d %d %d",ans1,ans2,ans3,ans4);
} 

JZOJ 4672 CF662B Graph Coloring

洛谷博客


JZOJ 4673 CF578D LCS Again

洛谷博客


后续

被WA支配的恐惧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值