CF 238E Meeting Her

最短路+搜索

本题考察搜索的奇技淫巧,让我口胡一下

先floyd把最短路跑出来。维护an[i]表示在i处且不在任何车上,到b的最少次数,那么最终答案是an[a]。正推无法更新答案,因为可能出现循环更新,我们考虑从终点逆推更新答案。

初始设an[b] = 0。然后我们O(n^2)地暴力枚举每一条车的线路+暴力枚举每一个站点,O(n)dfs来找出所有an[i] = 1的站点。然后继续暴力算出所有an[i] = 2的站点。。。。。。因为每次更新必然至少能更新一个点,所以有an[i] <= n。因此时间复杂度O(n^4)。

记忆化搜索不记忆化也能过。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 105
using namespace std;
namespace runzhe2000
{
    const int INF = 1000000000; 
    int n, m, a, b, d[N][N], timer, ecnt, vis[N], cnt[N], buscnt, s[N], t[N], must[N][N], an[N], last[N], f[N];
    struct edge{int next, to;}e[N*N];
    void addedge(int a, int b){e[++ecnt] = (edge){last[a], b}; last[a] = ecnt;}
    int dfs(int x, int y)
    {
        int tmp = -1;
        for(int i = last[x]; i; i = e[i].next)
        {
            int j = e[i].to;
            if(d[x][j] + d[j][y] == d[x][y] && d[x][j] < INF) tmp = max(tmp, dfs(j,y));
        }
        if(tmp == -1) tmp = INF;
        tmp = min(tmp, an[x] + 1); return tmp;
    }
    void main()
    {
        scanf("%d%d%d%d",&n,&m,&a,&b);
        memset(d,63,sizeof(d));
        for(int i = 1, u, v; i <= m; i++)
        {
            scanf("%d%d",&u,&v);
            d[u][v] = 1; addedge(u, v);
        }
        for(int i = 1; i <= n; i++) d[i][i] = 0;
        for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
        scanf("%d",&buscnt); 
        for(int i = 1; i <= buscnt; i++)
        {
            scanf("%d%d",&s[i],&t[i]);
            memset(cnt,0,sizeof(cnt));
            for(int j = 1; j <= n; j++)
                if(d[s[i]][j] + d[j][t[i]] == d[s[i]][t[i]] && d[s[i]][t[i]] < INF)
                    cnt[d[s[i]][j]]++;
            for(int j = 1; j <= n; j++)
                if(d[s[i]][j] + d[j][t[i]] == d[s[i]][t[i]] && d[s[i]][t[i]] < INF && cnt[d[s[i]][j]] == 1)
                    must[i][j] = 1;
        }
        memset(an,63,sizeof(an));
        for(an[b] = 0; ; )
        {
            bool ok = 1;
            for(int i = 1; i <= buscnt; i++)
                for(int j = 1; j <= n; j++) if(must[i][j])
                {
                    ++timer;
                    int ans = dfs(j, t[i]);
                    if(ans < an[j]) an[j] = ans, ok = 0;
                }
            if(ok) break;
        }
        printf("%d\n",an[a] < INF ? an[a] : -1);
    }
}
int main()
{
    runzhe2000::main(); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值