zoukankan      html  css  js  c++  java
  • 文化之旅

    传送门

    ovo这题没有靠谱的多项式复杂度的做法?!

    好吧我也不知道该怎么做,于是学了一个大佬的Floyd玄学算法。

    具体的实现还是很简单的,就是每次使用Floyd更新,必须要满足以下情况:

    1.当前三个点文化不互相排斥

    2.通往k(用于更新的点)的道路上所经过的文化与当前文化不互相排斥

    3.距离更小

    注意使用g[i][j][k]表示从i到j的路上排斥k文化,每次在更新的时候使用按位或来更新。

    这样就可以做了……orz

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<queue>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 50005;
    const int INF = 10000000;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    int n,k,m,s,t,c[105],a[105][105],dis[105][105],u,v,d;
    bool g[105][105][105];
    
    void floyd()
    {
        rep(k,1,n)
        rep(i,1,n)
        rep(j,1,n)
        {
        if(a[c[k]][c[i]] || a[c[j]][c[k]]) continue;//不符合第一种情况
        if(g[i][k][c[j]] || g[k][j][c[i]]) continue;//不符合第二种情况(注意这里不要把开始城市和结束城市搞混)
        if(dis[i][k] + dis[k][j] < dis[i][j])
        {
            rep(t,1,n) g[i][j][t] = g[i][k][t] | g[k][j][t];//枚举每一种文化并且进行更新
            g[i][j][c[k]] = 1;
            dis[i][j] = dis[i][k] + dis[k][j];//更新距离
        }
        }
    }
    
    int main()
    {
        n = read(),k = read(),m = read(),s = read(),t = read();
        rep(i,1,n)
        rep(j,1,n) dis[i][j] = INF;
        rep(i,1,n) c[i] = read(),dis[i][i] = 0;
        rep(i,1,k)
        rep(j,1,k) a[i][j] = read();
        rep(i,1,m)
        {
        u = read(),v = read(),d = read();
        if(!a[c[v]][c[u]] && c[u] != c[v]) dis[u][v] = min(dis[u][v],d);
        if(!a[c[u]][c[v]] && c[u] != c[v]) dis[v][u] = min(dis[v][u],d);//只有在符合条件的时候才更新距离
        }
        rep(i,1,n)
        rep(j,1,n) g[i][j][c[i]] = 1,g[i][j][c[j]] = 1;//设置路径上的文化排斥
        floyd();
        if(dis[s][t] == INF) printf("-1
    ");
        else printf("%d
    ",dis[s][t]);
        return 0;
    }
  • 相关阅读:
    perl教程
    信号量(semaphore)——POSIX信号量和System V信号量
    (C#习题) 杂题1
    (C#) 操作XML之遍历
    (C# 基础) Solution and Project
    (C#)枚举 Enumerations
    (WPF) 窗口间传参数
    (C#) 操作XML之查找
    (C#习题) 字符串
    (C#) VS类视图和对象浏览器图标
  • 原文地址:https://www.cnblogs.com/captain1/p/9604962.html
Copyright © 2011-2022 走看看