• 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
    ",ans);
    155     return 0;
    156 }
  • 相关阅读:
    ubuntu装openssh-client和openssh-server
    路由器开源系统openwrt配置页面定制
    linux 串口接收
    SHA算法
    密码学Hash函数
    椭圆曲线加密
    ElGamal密码
    Diffie-Hellman密钥交换
    RSA加密
    公钥密码学
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7635124.html
Copyright © 2020-2023  润新知