zoukankan      html  css  js  c++  java
  • 【xsy2193】Wallace 最大权闭合子图

    题目大意:给你一棵$n$个节点的树$a$,每个点有一个点权$val_i$,同时给你另一棵$n$个节点的树$b$。

    现在你需要在树$a$上找一个联通块,满足这些点在树$b$上也是连通的,同时树$a$的这个联通块的点权和要最大。

    数据范围:$n≤50$,$-1000≤val_i≤1000$。

    我们考虑钦定一个点作为跟,不妨设当前钦定的根为$x$。

    我们发现,如果要选择点$y$,那么由点$y$至$x$的路径上的点都需要选(无论是树$a$还是树$b$)

    然后这个就变成了一个经典的最大权闭合子图问题

    直接最小割判定即可。

    时间复杂度:玄学

     1 #include<bits/stdc++.h>
     2 #define M 320
     3 #define N 52
     4 #define INF 19890604
     5 using namespace std;
     6 
     7 struct edge{int u,v,next;}e[M]={0}; int head[M]={0},use=0;
     8 void add(int x,int y,int z){e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use++;}
     9 void Add(int x,int y,int z){add(x,y,z); add(y,x,0);}
    10 
    11 int dis[N]={0},S,T; queue<int> q;
    12 
    13 bool bfs(){
    14     memset(dis,0,sizeof(dis));
    15     q.push(S); dis[S]=1;
    16     while(!q.empty()){
    17         int u=q.front(); q.pop();
    18         for(int i=head[u];~i;i=e[i].next)
    19         if(e[i].v&&dis[e[i].u]==0){
    20             dis[e[i].u]=dis[u]+1;
    21             q.push(e[i].u);
    22         }
    23     }
    24     return dis[T];
    25 }
    26 
    27 int dfs(int x,int flow){
    28     if(x==T) return flow; int sum=0;
    29     for(int i=head[x];~i;i=e[i].next)
    30     if(e[i].v&&dis[x]+1==dis[e[i].u]){
    31         int k=dfs(e[i].u,min(flow,e[i].v));
    32         e[i].v-=k; e[i^1].v+=k;
    33         sum+=k; flow-=k;
    34         if(flow==0) return sum;
    35     }
    36     if(flow==0) dis[x]=-1;
    37     return sum;
    38 }
    39 
    40 int dinic(){int res=0; while(bfs()) res+=dfs(S,1<<30); return res;}
    41 
    42 vector<int> G1[N],G2[N];
    43 int val[N]={0},f1[N]={0},f2[N]={0},n;
    44 
    45 void dfs(int x,int fa,vector<int> G[],int f[]){
    46     f[x]=fa; if(fa) Add(x,fa,INF);
    47     for(int i=0;i<G[x].size();i++)
    48     if(G[x][i]!=fa) dfs(G[x][i],x,G,f);
    49 }
    50 
    51 int solve(int x){
    52     memset(head,-1,sizeof(head)); use=0;
    53     dfs(x,0,G1,f1);
    54     dfs(x,0,G2,f2);
    55     S=0; T=n+1;
    56     for(int i=1;i<=n;i++)
    57     if(val[i]>0) Add(S,i,val[i]);
    58     else Add(i,T,-val[i]);
    59     return dinic();
    60 }
    61 
    62 int main(){
    63     int sum=0; scanf("%d",&n);
    64     for(int i=1;i<=n;i++) scanf("%d",val+i),sum+=max(0,val[i]);
    65     for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),x++,y++,G1[x].push_back(y),G1[y].push_back(x);
    66     for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),x++,y++,G2[x].push_back(y),G2[y].push_back(x);
    67     
    68     int maxn=0;
    69     for(int i=1;i<=n;i++)
    70     maxn=max(maxn,sum-solve(i));
    71     cout<<maxn<<endl;
    72 }    
  • 相关阅读:
    redis报错io.lettuce.core.RedisCommandTimeoutException: Command timed out after
    showloading showtoast一起用
    uniapp,mpvue微信,支付宝兼容性说明
    uniapp 自定义组件
    Vue 函数式组件 functional
    mac uninstall node ,npm from official
    mpvue问题记录:组件方法执行机制
    linux 文件 分割重组
    MySql日期操作
    .NET Core连接数据库
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10582474.html
Copyright © 2011-2022 走看看