Codeforces 1220 E Tourism

题面

 

   可以发现一个边双必然是可以随意走的,所以我们就把原图求割边然后把边双缩成一个点,然后就是一个树上dp了。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=200005;
#define pb push_back
 
inline int read(){
    int x=0; char ch=getchar();
    for(;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x;
}
 
vector<int> G[N];
int n,a[N],dfn[N],low[N],lt[N],k,siz[N];
int hd[N],ne[N*2],to[N*2],num=1,tot[N],dc,m,s;
ll ltw[N],ans,M,mx[N];
bool ban[N*2];
 
inline void add(int x,int y){
    to[++num]=y,ne[num]=hd[x],hd[x]=num;
}
 
void dfs(int x,int fa){
    dfn[x]=low[x]=++dc;
     
    for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
        if(!dfn[to[i]]){
            dfs(to[i],x),low[x]=min(low[x],low[to[i]]);
            if(low[to[i]]>=dfn[to[i]]) ban[i]=ban[i^1]=1;
        }
        else low[x]=min(low[x],dfn[to[i]]);
}
 
void B(int x){
    lt[x]=k,ltw[k]+=a[x],siz[k]++;
    for(int i=hd[x];i;i=ne[i]) if(!ban[i]&&!lt[to[i]]) B(to[i]);
}
 
void dp(int x,int fa){
    tot[x]=siz[x]>1;
    for(int i:G[x]) if(i!=fa){
        dp(i,x),tot[x]+=tot[i],mx[x]=max(mx[x],mx[i]);
    }
     
    mx[x]+=ltw[x];
    if(tot[x]) ans+=ltw[x];
    else M=max(M,mx[x]);
}
 
inline void solve(){
    for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,i);
    for(int i=1;i<=n;i++) if(!lt[i]) k++,B(i);
 
    for(int i=1;i<=n;i++)
        for(int j=hd[i];j;j=ne[j]) if(lt[i]!=lt[to[j]]) G[lt[i]].pb(lt[to[j]]);
     
    dp(lt[s],0);
    ans+=M;
}
 
inline void check(){
    cout<<k<<' '<<lt[s]<<endl;
    for(int i=1;i<=k;i++){
        cout<<i<<"'s size is"<<siz[i]<<endl;
        for(int j:G[i]) cout<<j<<" ";
        cout<<endl;
    }
}
 
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1,u,v;i<=m;i++) u=read(),v=read(),add(u,v),add(v,u);
     
    s=read(),solve();
     
    cout<<ans<<endl;
     
//  check();
    return 0;
}

  

posted @   蒟蒻JHY  阅读(384)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
阅读排行:
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略
点击右上角即可分享
微信分享提示