首页 > 其他分享 >CF773D Perishable Roads

CF773D Perishable Roads

时间:2023-11-13 23:23:49浏览次数:27  
标签:int Perishable CF773D mn st maxn Roads times 我们

题目描述:

有一个 \(n\) 个点的图,对于每两个点 \((i,j)\) 之间都有一条长度为 \(w_{i,j}\) 的无向边。

给你一个点 \(t\),你需要构造一棵以 \(t\) 为根的生成树,使得\(\sum\limits_{i=1}^{n}s(i,t)\) 尽量小。\(s(i,t)\) 为 \(i\rightarrow t\) 的树上路径上的最小权值。

你需要对于每个 \(t\) 都求出答案。

数据范围:

\(n\le 2000\)

\(1\le w_i\le 10^9\)

思路:

首先我们手摸一下样例,显然我们希望尽可能使得整体的距离最小,则需要满足尽可能多的点都是经过最短边然后到达 \(t\)。

在进行正式的讲解之前,我们先进行一些定义:

  1. \(mn\) 表示最小的边长,\(st\) 表示最小的边连接的点

所以我们就可以将整个图分为两个部分:

  1. \(st\Rightarrow t\) 的这条链
  2. 以 \(st\) 为根且到 \(t\) 最小值为 \(mn\) 的一棵树

注意:最小边在树和链的连接处

然后我们分别考虑怎么计算这个两个部分。

对于链的部分,我们不难发现一个性质:必定存在一种最优方案,使得从st到t的这条链上边权单调不降

这个性质的证明也是比较简单的。

我们考虑反证法:如果有一条递减的边,则把这个点放到链起点的位置显然不会更劣。所以问题就转换为求一条最短路径的长度

所以我们以 \(st\) 为起点跑一边最短路,就可以得到以 \(i\) 为终点的链上的最小代价。


然后我们考虑如何计算树的部分的答案:

令整条路径上经过的点的数量为 \(x\),则一共 \(n-x\) 个在树上的点(这里的树不是整棵生成树)然后贡献就是 \((n-x)\times mn\)

然后我们发现这个东西不是很好计算,所以我们不妨对原式进行一些修改(这个改动我根本没想到)

将 \(x\) 的定义变为链上的边的数量,则贡献变为 \((n-x-1)\times mn\to (n-1)\times mn-x\times mn\)


所以我们不妨对于原图中的每一条边都减去 \(mn\)。

这样最后的答案就可以转变为 \(dis_t+(n-1)\times mn\)

后记:

关于一些疑问:

1. 为什么只需要进行一个 \(mn\) 两端的点就可以了?

仔细观察代码,我们在代码中有这样的几行

for(int j=1;j<=n;j++)if(j!=i)dis[i]=min(dis[i],g[j][i]*2);

所以我们不难发现,这个东西实际上包含了另外一种情况,具体的可以画图理解一些:
图片

对于这个图,显然 \(st=1\)

这个涉及到在处理的时候与 \(st\) 连边的有哪些点?

  1. 直接连边
  2. 经过一个转折点
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2005;
const int inf=1e18;
int n;
int g[maxn][maxn];
int mn=inf,st;
int vis[maxn],dis[maxn];
void Dijkstra(int st){
    for(int i=1;i<=n;i++)dis[i]=inf,vis[i]=0;
    vis[st]=1;
    for(int i=1;i<=n;i++){
        dis[i]=g[st][i];
        for(int j=1;j<=n;j++)if(j!=i)dis[i]=min(dis[i],g[j][i]*2);
    }
    for(int i=1;i<n;i++){
        int u=-1;
        for(int j=1;j<=n;j++){
            if(!vis[j]&&(u==-1||dis[j]<dis[u]))u=j;
        }
        vis[u]=1;
        for(int v=1;v<=n;v++){
            dis[v]=min(dis[v],dis[u]+g[u][v]);
        }
    }
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            scanf("%lld",&g[i][j]);
            g[j][i]=g[i][j];
            if(mn>g[i][j]){
                mn=g[i][j];
                st=i;
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            g[i][j]-=mn;
            g[j][i]-=mn;
        }
    }
    Dijkstra(st);
    for(int i=1;i<=n;i++){
        printf("%lld\n",dis[i]+mn*(n-1));
    }
    return 0;
}

可能讲的有些凌乱,还请多多海涵

标签:int,Perishable,CF773D,mn,st,maxn,Roads,times,我们
From: https://www.cnblogs.com/Candycar/p/17830578.html

相关文章

  • CF543B Destroying Roads
    好经典的题,因为暑假前集训做过类似的思想的题所以知道怎么处理这题由于要求最多的删去的边数,则等价于求最少保留几条边,很显然留下的边一定是最短路上的但问题是如果两条路不相交的话很简单,可事实是两条路径可以重叠一些部分,这些边用了两次可能可以使答案变优关于这种图上两条路......
  • CF1149D Abandoning Roads
    首先\(a\)边可以随便选。显然,若某条\(b\)边的两端位于同一\(a\)连通块,一定不会被我们考虑。剩下的\(b\)边一定会将两个\(a\)连通块相连。那么此时我们对于\(b\)边的约束是,位于一个环上的\(b\)边不能同时存在图中,即,我们的路径不能从当前连通块出发,经过至少一条\(b......
  • CodeForces 1149D Abandoning Roads
    洛谷传送门CF传送门考虑一条\(1\toi\)的路径是否在最小生成树上。称边权为\(a\)的边为轻边,边权为\(b\)的边为重边。轻边若不成环则一定在最小生成树上,因此先把轻边合并,这样形成了若干连通块。那么如果两点在一个连通块,它们只能通过轻边互达。同时,因为是树上路径,所......
  • CF671D Roads in Yusland
    1D8ya。设\(f_{u,i}\)表示覆盖了\(u\)子树并且向上覆盖到了深度为\(i\)的最小代价。考虑合并儿子\(v\):\[f'_{u,i}\gets\min\left(f_{u,i}+\min\limits_{j=1}^nf_{v,j},f_{v,i}+\min\limits_{j=1}^nf_{u,j}\right)\]相当于区间加,单点取\(\min\),区间求最小值。直接......
  • Roads in the North POJ - 2631 - 树的直径/树形dp
    题意:给出一棵无向树,求树的直径,即树上两点之间的最长距离分析:两种解法解法1:先任取一个点,找到距离该点最远的点u,再找到距离u最远的点v,那么u和v之间的路径就是一条直径。证明:只要找到了树的直径的一个端点,再从该点找到最远点就一定是直径的另一个端点。所以只需要证明第一次找到的......
  • CF671D Roads in Yusland 题解
    题目链接题目要求我们求出选出若干条路径并最小化花费,如果这是在链上,我们可以考虑直接枚举每条路径的右端点dp,那树呢?把路径剖分整个覆盖的集合就不一定连续了,没法dp,况且题目里给了很强的条件:路径一定是从孩子到祖先,硬转链用不上这个性质,貌似不太对。上述思考启发我们利用树的......
  • Constructing Roads
    ConstructingRoadsTimeLimit:2000/1000MS(Java/Others)    MemoryLimit:65536/32768K(Java/Others)TotalSubmission(s):17199    AcceptedSubmission(s):6529ProblemDescriptionThereareNvillages,whicharenumberedfrom1toN,andyou......
  • P3008 [USACO11JAN]Roads and Planes G
    P3008[USACO11JAN]RoadsandPlanesG思路按照分连通块的方法进行计算,并且如果不是本连通块的点,不能在现在的本次dfs中求解最小值。要一个一个的联通快进行标记。/*不能直接走disj的话,缩点的思想很重要首先尽量不要使用spfa进行走图,可能会卡对道路进行求连通块,对航线求度数......
  • Codeforces Round #Pi (Div. 2) E. President and Roads (最短路+强连通求割边)
    题目地址:codeforces#pi(DIV2)E题目很水。。就是先求两边最短路,然后把可能为最短路的边挑出来,然后判断是否yes只需要转化成无向图跑一遍tarjan,找出割边,割边就是yes,然后剩下的边就让它的值为最短路-1就行了,如果-1后变成了非正数,就是no.但是!!!居然卡spfa!!那是不是说cf以后就不......
  • UVa 11723 Numbering Roads (water ver.)
    11723-NumberingRoadsTimelimit:1.000secondshttp://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=2823Inmycountry,streetsdon’thavenames,eachofthemarejustgivenanumber......