题解 CF773D 【Perishable Roads】

编程入门 行业动态 更新时间:2024-10-09 17:29:54

<a href=https://www.elefans.com/category/jswz/34/1769599.html style=题解 CF773D 【Perishable Roads】"/>

题解 CF773D 【Perishable Roads】

简述一下题意:给出 n n n个点的完全图,对于完全图中的每个点 i i i, i i i作为终点时,要使其他每个点到点 i i i的“距离”和最小,对于每个点都输出这个最小值。
这里的“距离”是指对于其他每个点,那个点到点 i i i路径上的最小值。且对于每个点 i i i,计算答案时应保证图内每条边的方向一定。(有点难解释,可以参考原文)

题意很难表述清楚,建议看懂原题后再来看此题解。

考虑对于每个终点 i i i,最后连接所有点后图的形态,应该是一棵树接上一条链。如图:


我会贪心&&搜索!

从终点开始倒搜,对于当前搜到的点 n o w now now,每次找到未 v i s vis vis的且与 n o w now now相连的边权最小的点,向那个点继续搜。

很显然这个想法是非常非常错误的,直接排除


考虑优化贪心:

既然让每个点到终点路径上的最小边权和最小,那么很容易想到将所有点都连到边权最小的边的一端,再从这个点连向终点。 ( ( (下文我们将这个点称为“最小点” ) ) )

但这个还是错误的,如果连向终点的那条边权值特别大 ( I N F ) (INF) (INF),那么答案就会非常劣。如图:

那怎么办呢?我们就考虑让“最小点”去间接的连向终点,即从那些直接连向“最小点”的点中取一些出来,与“最小点”构成一条链,使这一条链加上那棵树的答案更优。我们称这条链 ( ( (起点为最小点,终点为 t t t ) ) )的答案为 d i s [ t ] dis[t] dis[t]。如图:

怎么计算答案呢?我们设那条链上除终点外有 x x x个点,那么那棵树上就有 n − 1 − x n-1-x n−1−x个点,设最小边长度为 m i n n minn minn,那么答案为 d i s [ t ] + m i n n ∗ ( n − 1 − x ) dis[t]+minn*(n-1-x) dis[t]+minn∗(n−1−x)。这个 x x x很难计算,考虑消去。即计算 d i s [ t ] dis[t] dis[t]前先对所有边权减去一个 m i n n minn minn,设新链答案为 d i s ′ [ t ] dis&#x27;[t] dis′[t],那么答案会变成 ( d i s ′ [ t ] + m i n n ∗ x ) + m i n n ∗ ( n − 1 − x ) (dis&#x27;[t]+minn*x)+minn*(n-1-x) (dis′[t]+minn∗x)+minn∗(n−1−x),即 d i s ′ [ t ] + m i n n ∗ ( n − 1 ) dis&#x27;[t]+minn*(n-1) dis′[t]+minn∗(n−1), x x x就消去了。所以我们计算 d i s ′ [ t ] dis&#x27;[t] dis′[t]即可。

因为要求最优解,我们跑最短路求 d i s dis dis ( ( (定义见上 ) ) )。一开始的状态是上面图2,即向终点直接连边,所以赋为终点与最小点的边权 ( ( (详见代码 ) ) )。还有一种状态,即考虑那条链上有3个点。设加入的为点 j j j,那么链的答案可能为最小点到终点的答案加上 j j j到终点的答案,即 f [ i ] [ j ] ∗ 2 f[i][j]*2 f[i][j]∗2 ( ( ( f f f数组为邻接矩阵, i i i是终点 ) ) )。最后 d i j dij dij松弛即可 ( ( (模板 ) ) )。

#include<bits/stdc++.h>
using namespace std;
int n,f[3005][3005],vis[3005],dis[3005];
inline int read(){int ret=0,ff=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();}while(isdigit(ch)){ret=(ret<<3)+(ret<<1)+(ch^48);ch=getchar();}return ret*ff;
}
inline void write(int x){if(x<0){putchar('-');x=-x;}if(x>9)write(x/10);putchar(x%10+48);
}
void dij(int st){for(int i=1;i<=n;i++){dis[i]=f[st][i];for(int j=1;j<=n;j++)if(i!=j) dis[i]=min(dis[i],f[i][j]*2);}vis[st]=1;for(int i=1;i<=n-1;i++){int minn=2e9+1,k;for(int j=1;j<=n;j++)if(!vis[j]&&dis[j]<minn){minn=dis[j];k=j;}vis[k]=1;for(int j=1;j<=n;j++)if(!vis[j])dis[j]=min(dis[j],dis[k]+f[j][k]);}
}
int main(){int minn=2e9+1,k;n=read();for(int i=1;i<=n-1;i++)for(int j=1;j<=n-i;j++){f[i][i+j]=f[i+j][i]=read();if(f[i][i+j]<minn){minn=f[i][i+j];k=i;}}for(int i=1;i<=n-1;i++)for(int j=1;j<=n-i;j++){f[i][i+j]-=minn;f[i+j][i]=f[i][i+j];}		dij(k);for(int i=1;i<=n;i++) printf("%d ",dis[i]+minn*(n-1));return 0;
}

更多推荐

题解 CF773D 【Perishable Roads】

本文发布于:2024-03-13 00:52:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732814.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:题解   CF773D   Roads   Perishable

发布评论

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

>www.elefans.com

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