• 【学习笔记】[EGOI2023] Bikes vs Cars


    题目链接

    警惕出题人为了不让你看出来构造是生成树而用了 2023 2023 2023这个数字😅

    下文中宽度为 w w w的边表示分配给自行车的宽度。

    考虑如何判定无解。如果存在 i , j , k i,j,k i,j,k使得 b i , j < min ⁡ ( b i , k , b k , j ) b_{i,j}<\min(b_{i,k},b_{k,j}) bi,j<min(bi,k,bk,j)或者 c i , j < min ⁡ ( c i , k , c k , j ) c_{i,j}<\min(c_{i,k},c_{k,j}) ci,j<min(ci,k,ck,j),那么原问题一定无解。

    我们考虑,对于两个点 ( i , j ) (i,j) (i,j),如果 b i , j + c i , j ≥ W b_{i,j}+c_{i,j}\ge W bi,j+ci,jW,那么我们可以贪心的在 i , j i,j i,j之间连一条宽度为 b i , j b_{i,j} bi,j的边(给自行车道)以及一条宽度为 W − c i , j W-c_{i,j} Wci,j的边(给机动车道),这并不会影响答案;反之,如果 b i , j + c i , j < W b_{i,j}+c_{i,j}bi,j+ci,j<W,那么我们必然不能在 i , j i,j i,j之间连边。因此,考虑贪心的连上这些边,如果无法满足条件,那么原问题无解(我们已经尽可能的加入所有边了)。

    考虑加上边数的限制,我们自然而然的想到分别求解这两类边对应的最大生成树,显然如果边数不为 2 n − 2 2n-2 2n2那么原问题肯定无解;否则我们发现这样的生成树恰好满足我们的构造。(不需要 Floyd \text{Floyd} Floyd检验,可以结合第一步判定无解的过程想一想为什么)

    复杂度 O ( n 3 ) O(n^3) O(n3)。但是显然判定无解的过程可以优化到 O ( n 3 w ) O(\frac{n^3}{w}) O(wn3)

    #include
    #define ll long long
    #define pb push_back
    #define fi first
    #define se second
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=505;
    int n,W,m,a[N][N],b[N][N];
    int fa[N];
    struct node{
        int x,y,z;
        bool operator <(const node &a)const{
            return z>a.z;
        }
    }e[N*N];
    vector<node>res;
    int find(int x){
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0),cout.tie(0);
        cin>>n>>W;
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                cin>>b[i][j];
                b[j][i]=b[i][j];
            }
        }
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                cin>>a[i][j];
                a[j][i]=a[i][j];
            }
        }
        for(int i=0;i<n;i++)a[i][i]=b[i][i]=inf;
        for(int k=0;k<n;k++){
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(a[i][j]<min(a[i][k],a[k][j])||b[i][j]<min(b[i][k],b[k][j])){
                        cout<<"NO";
                        return 0;
                    }
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(a[i][j]+b[i][j]>=W){
                    e[++m]={i,j,a[i][j]};
                }
            }
        }
        sort(e+1,e+1+m);
        for(int i=0;i<n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            int u=e[i].x,v=e[i].y,w=e[i].z;
            if(find(u)!=find(v))fa[fa[u]]=fa[v],res.pb({u,v,w});
        }
        for(int i=0;i<n;i++)fa[i]=i;
        m=0;
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                if(a[i][j]+b[i][j]>=W){
                    e[++m]={i,j,b[i][j]};
                }
            }
        }
        sort(e+1,e+1+m);
        for(int i=1;i<=m;i++){
            int u=e[i].x,v=e[i].y,w=e[i].z;
            if(find(u)!=find(v))fa[fa[u]]=fa[v],res.pb({u,v,W-w});
        }
        if(res.size()!=2*n-2){
            cout<<"No";
            return 0;
        }
        cout<<res.size()<<"\n";
        for(auto e:res){
            cout<<e.x<<" "<<e.y<<" "<<e.z<<"\n";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
  • 相关阅读:
    深度学习基础宝典---激活函数、Batch Size、归一化
    算法设计与分析 SCAU19184 传球游戏
    ​Linux·i2c驱动架构​
    【死磕JVM】用Arthas排查JVM内存 真爽!我从小用到大
    单日 5000 亿行 / 900G 数据接入,TDengine 3.0 在中国地震台网中心的大型应用
    【深度学习】【三维重建】windows10环境配置tiny-cuda-nn详细教程
    【Linux】线程安全
    前缀和——DP34 【模板】前缀和
    ctf:kali工具wireshark,nmap
    DevOps|乱谈开源社区、开源项目与企业内部开源
  • 原文地址:https://blog.csdn.net/cqbzlydd/article/details/134384973