$n \leq 50$的两棵树,同编号的点有同个点权,问如何选一个点集,使得这个点集里的点在两棵树内都连通,且总点权最大,输出最大点权和。
枚举一个点在答案里,然后把树以它为根,此时选儿子一定要选父亲,构成最大权闭合子图。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<set> 7 //#include<queue> 8 #include<algorithm> 9 #include<stdlib.h> 10 using namespace std; 11 12 #define LL long long 13 int qread() 14 { 15 char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1); 16 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f; 17 } 18 19 //Pay attention to '-' , LL and double of qread!!!! 20 21 int n,m; 22 #define maxn 111 23 #define maxm 1111 24 struct Edge{int to,next,flow,cap;}; 25 struct Network 26 { 27 Edge edge[maxm]; int first[maxn],le,n; 28 void clear(int N) {le=2; memset(first,0,sizeof(first)); n=N;} 29 void in(int x,int y,int cap) {Edge &e=edge[le]; e.to=y; e.cap=cap; e.flow=0; e.next=first[x]; first[x]=le++;} 30 void insert(int x,int y,int cap) {in(x,y,cap); in(y,x,0);} 31 int dis[maxn]; int que[maxn],cur[maxn],head,tail,s,t; 32 bool bfs() 33 { 34 memset(dis,0,sizeof(dis)); dis[s]=1; 35 head=tail=0; que[tail++]=s; 36 while (head!=tail) 37 { 38 int x=que[head++]; 39 for (int i=first[x];i;i=edge[i].next) 40 { 41 Edge &e=edge[i]; 42 if (!dis[e.to] && e.cap>e.flow) 43 { 44 dis[e.to]=dis[x]+1; 45 que[tail++]=e.to; 46 } 47 } 48 } 49 return dis[t]; 50 } 51 int dfs(int x,int a) 52 { 53 if (x==t || !a) return a; 54 int flow=0,f; 55 for (int &i=cur[x];i;i=edge[i].next) 56 { 57 Edge &e=edge[i]; 58 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(e.cap-e.flow,a)))>0) 59 { 60 flow+=f; e.flow+=f; 61 edge[i^1].flow-=f; a-=f; 62 if (!a) break; 63 } 64 } 65 return flow; 66 } 67 int Dinic(int S,int T) 68 { 69 s=S; t=T; 70 int ans=0; 71 while (bfs()) 72 { 73 for (int i=1;i<=n;i++) cur[i]=first[i]; 74 ans+=dfs(s,0x3f3f3f3f); 75 } 76 return ans; 77 } 78 bool vis[maxn]; 79 void dfs(int x) 80 { 81 vis[x]=1; 82 for (int i=first[x];i;i=edge[i].next) 83 { 84 Edge &e=edge[i]; 85 if (e.cap>e.flow && !vis[e.to]) dfs(e.to); 86 } 87 } 88 }g; 89 90 struct EE{int to,next;}; 91 struct Tree 92 { 93 EE edge[maxn<<1]; int first[maxn],le; 94 Tree() {le=2;} 95 void in(int x,int y) {EE &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;} 96 void insert(int x,int y) {in(x,y); in(y,x);} 97 }t[2]; 98 99 int ss[maxn]; 100 void dfs(int p,int x,int fa) 101 { 102 for (int i=t[p].first[x];i;i=t[p].edge[i].next) 103 { 104 EE &e=t[p].edge[i]; if (e.to==fa) continue; 105 g.insert(e.to,x,0x3f3f3f3f); dfs(p,e.to,x); 106 } 107 } 108 109 int main() 110 { 111 n=qread(); int sum=0; 112 for (int i=1;i<=n;i++) {ss[i]=qread(); if (ss[i]>0) sum+=ss[i];} 113 for (int i=1;i<n;i++) t[0].insert(qread()+1,qread()+1); 114 for (int i=1;i<n;i++) t[1].insert(qread()+1,qread()+1); 115 int s=n+1,t=s+1; 116 int ans=0; 117 for (int i=1;i<=n;i++) 118 { 119 g.clear(t); 120 dfs(0,i,0); dfs(1,i,0); 121 for (int j=1;j<=n;j++) if (ss[j]>0) g.insert(s,j,ss[j]); 122 else g.insert(j,t,-ss[j]); 123 ans=max(ans,sum-g.Dinic(s,t)); 124 } 125 printf("%d\n",ans); 126 return 0; 127 }