嘘~ 正在从服务器偷取页面 . . .

洛谷P1453 城市环路 题解


洛谷P1453 城市环路 题解

题目链接:P1453 城市环路

题意

整个城市可以看做一个 \(n\) 个点,\(n\) 条边的单圈图(保证图连通),唯一的环便是绕城的环路。保证环上任意两点有且只有 \(2\) 条简单路径互通。图中的其它部分皆隶属城市郊区。

现在,有一位名叫 Jim 的同学想在 B 市开店,但是任意一条边的 \(2\) 个点不能同时开店,每个点都有一定的人流量,第 \(i\) 个点的人流量是 \(p_i\),在该点开店的利润就等于 \(p_i×k\),其中 \(k\) 是一个常数。

Jim 想尽量多的赚取利润,请问他应该在哪些地方开店?

  • 对于 \(100\%\) 的数据,保证 \(1 \leq n \leq 10^5\)\(1 \leq p_i \leq 10^4\)\(0 \leq u, v < n\)\(0 \leq k \leq 10^4\)\(k\) 的小数点后最多有 \(6\) 位数字。

显然这是一个基环树dp

对于基环树dp,

基本思想就是在那个环上找两个相邻点

分别作为根节点跑树形dp

因为本题中这两个点不能同时选,所以这么做是可以得到正确答案的

转移方程太简单了,直接看代码吧

相信做这个题的不可能树形dp都不会吧。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(1e5+15)

struct Edge
{
    int u,v,next;
}e[N<<1];
int n,fa[N],f[N][2],p[N],head[N],pos=1,S,T;
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void addEdge(int u,int v)
{
    e[++pos]={u,v,head[u]};
    head[u]=pos;
}
void dfs(int u,int Fa)
{
    f[u][1]=p[u];f[u][0]=0;
    for(int i=head[u]; i; i=e[i].next)
    {
        int v=e[i].v;
        if(v==Fa)continue;
        dfs(v,u);
        f[u][0]+=max(f[v][0],f[v][1]);
        f[u][1]+=f[v][0];
    }
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1; i<=n; i++)
        cin >> p[i],fa[i]=i;
    for(int i=1,u,v; i<=n; i++)
    {
        cin >> u >> v;++u;++v;
        if(find(u)==find(v)){S=u,T=v;continue;}
        addEdge(u,v);addEdge(v,u);
        fa[find(u)]=find(v);
    }
    double k; cin >> k;
    dfs(S,0); int res=f[S][0];
    dfs(T,0); res=max(res,f[T][0]);
    cout << fixed << setprecision(1);
    cout << (double)res*k << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录