51nod 1325 两棵树的问题(最大权闭合图)

Posted 7391_KID

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1325 两棵树的问题(最大权闭合图)相关的知识,希望对你有一定的参考价值。

分析:枚举根结点,每次考虑必然包含根结点的子图。如果i在图中,则i在两棵树中的父亲也必然在子图中,所以从i向两个父亲各连一条边,问题就转化为求最大权闭合子图了,每次枚举根结点更新答案即可。

  1 #include<iostream>
  2 #include<vector>
  3 #include<queue>
  4 #include<stack>
  5 #include<cstdio>
  6 #include<cstring>
  7 using namespace std;
  8 const int maxn=55,INF=1e9;
  9 struct Edge{
 10     int from,to,cap,flow;
 11     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
 12 };
 13 struct ISAP{
 14     int n,s,t;
 15     vector<Edge> edges;
 16     vector<int> G[maxn];
 17     bool vis[maxn];
 18     int d[maxn];
 19     int cur[maxn];
 20     int p[maxn];
 21     int num[maxn];
 22 
 23     void init(int n){
 24         this->n=n;
 25         edges.clear();
 26         for(int i=0;i<n;i++)G[i].clear();
 27     }
 28 
 29     void AddEdge(int from,int to,int cap){
 30         edges.push_back(Edge(from,to,cap,0));
 31         edges.push_back(Edge(to,from,0,0));
 32         G[from].push_back(edges.size()-2);
 33         G[to].push_back(edges.size()-1);
 34     }
 35 
 36     void BFS(){
 37         memset(vis,0,sizeof(vis));
 38         queue<int> Q;
 39         Q.push(t);
 40         d[t]=0;
 41         vis[t]=1;
 42         while(!Q.empty()){
 43             int x=Q.front();Q.pop();
 44             for(int i=0;i<G[x].size();i++){
 45                 Edge &e=edges[G[x][i]^1];
 46                 if(e.flow==e.cap)continue;
 47                 if(!vis[e.from]){
 48                     vis[e.from]=1;
 49                     d[e.from]=d[x]+1;
 50                     Q.push(e.from);
 51                 }
 52             }
 53         }
 54     }
 55 
 56     int Augment(){
 57         int x=t,a=INF;
 58         while(x!=s){
 59             Edge &e=edges[p[x]];
 60             a=min(a,e.cap-e.flow);
 61             x=edges[p[x]].from;
 62         }
 63         x=t;
 64         while(x!=s){
 65             edges[p[x]].flow+=a;
 66             edges[p[x]^1].flow-=a;
 67             x=edges[p[x]].from;
 68         }
 69         return a;
 70     }
 71 
 72     int Maxflow(int s,int t){
 73         this->s=s;this->t=t;
 74         int flow=0;
 75         BFS();
 76         memset(num,0,sizeof(num));
 77         for(int i=0;i<n;i++)num[d[i]]++;
 78         int x=s;
 79         memset(cur,0,sizeof(cur));
 80         while(d[s]<n){
 81             if(x==t){
 82                 flow+=Augment();
 83                 x=s;
 84             }
 85             int ok=0;
 86             for(int i=cur[x];i<G[x].size();i++){
 87                 Edge &e=edges[G[x][i]];
 88                 if(e.cap>e.flow&&d[x]==d[e.to]+1){
 89                     ok=1;
 90                     p[e.to]=G[x][i];
 91                     cur[x]=i;
 92                     x=e.to;
 93                     break;
 94                 }
 95             }
 96             if(!ok){
 97                 int m=n-1;
 98                 for(int i=0;i<G[x].size();i++){
 99                     Edge &e=edges[G[x][i]];
100                     if(e.cap>e.flow)m=min(m,d[e.to]);
101                 }
102                 if(--num[d[x]]==0)break;
103                 num[d[x]=m+1]++;
104                 cur[x]=0;
105                 if(x!=s)x=edges[p[x]].from;
106             }
107         }
108         return flow;
109     }
110 }isap;
111 
112 int v[maxn],s,t,n;
113 int G[2][maxn][maxn],p[2][maxn];
114 void buildtree(int root,int idx){
115     for(int i=0;i<n;i++){
116         if(G[idx][root][i]&&p[idx][root]!=i){
117             p[idx][i]=root;
118             buildtree(i,idx);
119         }
120     }
121 }
122 void AddAllEdge(){
123     for(int i=0;i<n;i++){
124         if(v[i]>0)isap.AddEdge(s,i,v[i]);
125         else if(v[i]<0)isap.AddEdge(i,t,-v[i]);
126         if(p[0][i]==i)continue;
127         isap.AddEdge(i,p[0][i],INF);
128         if(p[0][i]!=p[1][i]);
129             isap.AddEdge(i,p[1][i],INF);
130     }
131 }
132 
133 int main(){
134 //    freopen("e:\\\\in.txt","r",stdin);
135     scanf("%d",&n);
136     s=n,t=n+1;
137     memset(G,0,sizeof(G));
138     int a,b,sum=0,ans=0;
139     for(int i=0;i<n;i++){scanf("%d",&v[i]);sum+=v[i]>0?v[i]:0;}
140     for(int idx=0;idx<2;idx++){
141         for(int i=0;i<n-1;i++){
142             scanf("%d%d",&a,&b);
143             G[idx][a][b]=1;
144             G[idx][b][a]=1;
145         }
146     }
147     for(int i=0;i<n;i++){
148         p[0][i]=i;p[1][i]=i;
149         buildtree(i,0);buildtree(i,1);
150         isap.init(n+2);
151         AddAllEdge();
152         ans=max(ans,sum-isap.Maxflow(s,t));
153     }
154     printf("%d\\n",ans);
155     return 0;
156 }

 

以上是关于51nod 1325 两棵树的问题(最大权闭合图)的主要内容,如果未能解决你的问题,请参考以下文章

51nod1325 两棵树的问题

[51nod1325]两棵树的问题

[不知道哪来的题] 完美理论

51nod-1322: 关于树的函数

[51nod1673]树有几多愁

51nod 1673 树有几多愁