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

编程入门 行业动态 更新时间:2024-10-19 08:47:49

【<a href=https://www.elefans.com/category/jswz/34/1770117.html style=学习笔记】[EGOI2023] Bikes vs Cars"/>

【学习笔记】[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,j​≥W,那么我们可以贪心的在 i , j i,j i,j之间连一条宽度为 b i , j b_{i,j} bi,j​的边(给自行车道)以及一条宽度为 W − c i , j W-c_{i,j} W−ci,j​的边(给机动车道),这并不会影响答案;反之,如果 b i , j + c i , j < W b_{i,j}+c_{i,j}<W bi,j​+ci,j​<W,那么我们必然不能在 i , j i,j i,j之间连边。因此,考虑贪心的连上这些边,如果无法满足条件,那么原问题无解(我们已经尽可能的加入所有边了)。

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

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

#include<bits/stdc++.h>
#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";}
}

更多推荐

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

本文发布于:2023-11-15 01:02:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1590898.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:学习笔记   Cars   Bikes

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!