zoukankan      html  css  js  c++  java
  • 【洛谷6830】[IOI2020] 连接擎天树(趣题)

    点此看题面

    • 有一张(n)个点的简单无向图,给定每对点之间的简单路径条数(p_{i,j})
    • 求构造一张可能的图,或判断无解。
    • (nle10^3,forall ple3)

    对于(p=1)的情况

    如果我们用并查集合并每一对(p_{i,j}=1)(i,j),显然如果并查集中一个连通块里存在两点之间(p ot=1),就必然无解。

    考虑(p=1)意味着两点之间只有一条简单路径,故发现只要对每个连通块随便构造出一棵树,然后就可以把这整个块缩成一个点。

    于是(p=1)的情况就不复存在了。

    对于(p=2)的情况

    同样,我们用并查集合并每一对(p_{i,j}=2)(i,j),显然如果并查集中一个连通块里存在两点之间(p ot=2)。就必然无解。

    然后我们考虑每一个连通块,发现只要给这个连通块随便建一个环就可以了。

    特别注意,如果一个连通块只有两个点,此时该连通块是无法构成环的。

    对于(p=3)的情况

    其实,只要存在(p=3),就必然无解。

    如果存在(p_{A,B}=3),则下图是最简单的一种情况:

    而此时,从(C)(D)存在(4)条路径((CAD,CBD,CABD,CBAD)),超出了题目中给定的限制。

    因此,(p=3)的情况不存在。

    于是这道题就做完了。

    代码:(O(n^2))

    #include "supertrees.h"
    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000
    #define Array vector<vector<int> >
    using namespace std;
    int n,w[N+5],k[N+5],c[N+5],f[N+5];I int fa(CI x) {return f[x]^x?f[x]=fa(f[x]):x;}//并查集
    Array b;int construct(Array p)
    {
    	RI i,j,x,y;for(n=p[0].size(),b.resize(n),i=0;i^n;++i) f[i]=i,b[i].resize(n);//初始化
    	for(i=0;i^n;++i) for(j=0;j^n;++j) if(p[i][j]==3) return 0;//如果存在3,必然无解
    	for(i=0;i^n;++i) for(j=0;j^n;++j) p[i][j]==1&&(x=fa(i))^(y=fa(j))&&(f[x]=y,b[x][y]=b[y][x]=1);//把1在并查集上合并
    	for(i=0;i^n;++i) for(j=0;j^n;++j) if(i^j&&p[i][j]^1&&fa(i)==fa(j)) return 0;//判断是否存在矛盾
    	for(i=0;i^n;++i) w[i]=(k[i]=fa(i))==i;for(i=0;i^n;++i) f[i]=i;//k记录每个连通块的根,w记录每个点是否为根(缩点)
    	for(i=0;i^n;++i) if(w[i]) for(j=0;j^n;++j) w[j]&&p[i][j]==2&&(x=fa(i))^(y=fa(j))&&(f[x]=y);//把2在并查集上合并
    	for(i=0;i^n;++i) for(j=0;j^n;++j) if(i^j&&p[i][j]^2&&fa(k[i])==fa(k[j])) return 0;//判断是否存在矛盾
    	for(i=0;i^n;++i) w[i]&&fa(i)^i&&(b[k[fa(i)]][i]=b[i][k[fa(i)]]=1,k[fa(i)]=i,++c[fa(i)]);//k记录上次连边的点,建环
    	for(i=0;i^n;++i) if(w[i]&&fa(i)==i&&k[i]^i) {if(c[i]==1) return 0;b[k[i]][i]=b[i][k[i]]=1;}//如果存在两个点的环则无解,否则补全环
    	return build(b),1;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    JavaScript中的__proto__
    移动前端调试页面–weinre
    nodo合并多个mp3文件
    enctype和Content-type有什么关系
    vscode 实用的插件
    前端跨域问题及解决方案
    小小的js
    如何使用eslint
    RN记录
    numpy的索引
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6830.html
Copyright © 2011-2022 走看看