zoukankan      html  css  js  c++  java
  • 最大权闭合图

    poj2987 Firing  http://poj.org/problem?id=2987

    最大权闭合图模板题。闭合图就是,对于一个点集V,如果他们的所有的边所指向的点都在点集V中,则这个点集加上他们的边是闭合图。

    这种题就是每个点有权值正负零都有可能,选某个点u,如果必须选v,则我们设u,v有一条有向边。最后要我们有一种选取方案使得所选的点权值和最大。这就是最大权闭合图。

    解法用的是最大流来解。

    最大流==最小割

    最小割=减掉流量总和最少的一些边使得源点s和汇点t不连通。

         

    建图方法是:s源点到所有正权点连流量为那个点权值的边,所有负权点到汇点t连流量为负权绝对值的边。原来图中的依赖关系正常建边,流量定为inf。

    跑出来的最大流就是最小割。用所有正权的和减去最小割就是可获得的最大权。

    证明,因为中间的都是inf,所以最小割肯定是割到与s连的或者与t连的边。那么就是我们选择一些正权或者负权,并且我们都是选小的。也就是说对于正权到s这里,如果正权很小,并且选他就必须选一些负权很大的边,那么我们在最小割中也会选这个正权小的,使得st不连通。反之,如果负权那里小,我们就会选择割负权。最后正权的总和减去最小割。

    接下来就是算最小割时候的最少点,即第一问。第一问问的是最少解雇几个人,解雇是挣钱的,也就是最小割不会割到的,也就是边上还有流量的,所以dfs判断是看边流量是否为零,如果不为零说明没被最小割割到,说明解雇这个人是挣钱的,ans++。

    从源点dfs去搜索残留网络,因为和源点连接的点都是权值为正的,是我们要解雇的人的集合,如果残留网络的边还为正,则这时候则表示fire这个点可以有收益。

    dinic

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 typedef __int64 LL;
      7 const LL inf=0x3f3f3f3f3f3f3f3fLL;
      8 class Dinic { ///最大流(MV^2*ME)
      9     typedef LL typef;///流量的类型
     10     static const int ME=1000000;///边的个数
     11     static const int MV=5010;///点的个数
     12     int temp[MV],cur[MV],level[MV],path[MV];
     13     bool used[MV];
     14     queue<int> q;
     15     typef flow;
     16     bool bfs(int s,int t) {
     17         mt(level,-1);
     18         while(!q.empty()) q.pop();
     19         q.push(s);
     20         level[s]=1;
     21         while(!q.empty()) {
     22             int u=q.front();
     23             q.pop();
     24             for(int i=g.head[u]; ~i; i=g.e[i].next) {
     25                 int v=g.e[i].v;
     26                 if(level[v]==-1&&g.e[i].flow) {
     27                     level[v]=level[u]+1;
     28                     q.push(v);
     29                     if(v==t) return true;
     30                 }
     31             }
     32         }
     33         return false;
     34     }
     35 public:
     36     struct G {
     37         struct E {
     38             int u,v,next;
     39             typef flow;
     40         } e[ME];
     41         int le,head[MV];
     42         void init() {
     43             le=0;
     44             mt(head,-1);
     45         }
     46         void add(int u,int v,typef flow) {
     47             e[le].u=u;
     48             e[le].v=v;
     49             e[le].flow=flow;
     50             e[le].next=head[u];
     51             head[u]=le++;
     52         }
     53     } g;
     54 public:
     55     typef getflow() {
     56         return flow;
     57     }
     58     void init() {
     59         g.init();
     60     }
     61     void add(int u,int v,typef flow) {
     62         g.add(u,v,flow);
     63         g.add(v,u,0);
     64     }
     65     void solve(int s,int t) {
     66         int p,tempp;
     67         typef now;
     68         bool flag;
     69         flow=0;
     70         while(bfs(s,t)) {
     71             for(int i=0; i<MV; i++) {
     72                 temp[i]=g.head[i];
     73                 used[i]=true;
     74             }
     75             p=1;
     76             path[p]=s;
     77             while(p) {
     78                 int u=path[p];
     79                 if(u==t) {
     80                     now=inf;
     81                     for(int i=1; i<p; i++) {
     82                         now=min(now,g.e[cur[path[i]]].flow);
     83                     }
     84                     flow+=now;
     85                     for(int i=1; i<p; i++) {
     86                         int j=cur[path[i]];
     87                         g.e[j].flow-=now;
     88                         g.e[j^1].flow+=now;
     89                         if(!g.e[j].flow) tempp=i;
     90                     }
     91                     p=tempp;
     92                 } else {
     93                     flag=false;
     94                     for(int i=temp[u]; ~i; i=g.e[i].next) {
     95                         int v=g.e[i].v;
     96                         if(used[v]&&g.e[i].flow&&level[u]+1==level[v]) {
     97                             cur[u]=i;
     98                             temp[u]=g.e[i].next;
     99                             flag=true;
    100                             path[++p]=v;
    101                             break;
    102                         }
    103                     }
    104                     if(flag) continue;
    105                     p--;
    106                     used[u]=false;
    107                 }
    108             }
    109         }
    110     }
    111 } dinic;
    112 bool vis[5010];
    113 void dfs(int u,int t) {
    114     if(u==t) return ;
    115     vis[u]=true;
    116     for(int i=dinic.g.head[u]; ~i; i=dinic.g.e[i].next) {
    117         int v=dinic.g.e[i].v;
    118         if(dinic.g.e[i].flow&&!vis[v]) {
    119             dfs(v,t);
    120         }
    121     }
    122 }
    123 int main() {
    124     int n,m;
    125     while(~scanf("%d%d",&n,&m)) {
    126         dinic.init();
    127         LL sum=0;
    128         int s=0,t=n+1;
    129         for(int i=1,val; i<=n; i++) {
    130             scanf("%d",&val);
    131             if(val>0) {
    132                 sum+=val;
    133                 dinic.add(s,i,val);
    134             } else {
    135                 dinic.add(i,t,-val);
    136             }
    137         }
    138         while(m--) {
    139             int u,v;
    140             scanf("%d%d",&u,&v);
    141             dinic.add(u,v,inf);
    142         }
    143         dinic.solve(s,t);
    144         mt(vis,0);
    145         dfs(s,t);
    146         int ans=0;
    147         for(int i=1; i<=n; i++) {
    148             if(vis[i]) ans++;
    149         }
    150         printf("%d %I64d
    ",ans,sum-dinic.getflow());
    151     }
    152     return 0;
    153 }
    View Code

     sap

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #define mt(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 typedef __int64 LL;
      7 const LL inf=0x3f3f3f3f3f3f3f3fLL;
      8 class Sap { ///最大流 O(MV*ME^2)
      9     typedef LL typef;///流量的类型
     10     static const int ME=1000000;///边的个数
     11     static const int MV=5010;///点的个数
     12     int n,dep[MV],gap[MV],cur[MV],S[MV],top,i,inser;
     13     typef flow;
     14     queue<int> q;
     15     void bfs(int s,int t) {
     16         mt(dep,-1);
     17         mt(gap,0);
     18         while(!q.empty()) q.pop();
     19         gap[0]=1;
     20         dep[t]=0;
     21         q.push(t);
     22         while(!q.empty()) {
     23             int u=q.front();
     24             q.pop();
     25             for(int i=g.head[u]; ~i; i=g.e[i].next) {
     26                 int v=g.e[i].v;
     27                 if(dep[v]!=-1) continue;
     28                 q.push(v);
     29                 dep[v]=dep[u]+1;
     30                 ++gap[dep[v]];
     31             }
     32         }
     33     }
     34 public:
     35     struct G {
     36         struct E {
     37             int u,v,next;
     38             typef flow;
     39         } e[ME];
     40         int le,head[MV];
     41         void init() {
     42             le=0;
     43             mt(head,-1);
     44         }
     45         void add(int u,int v,typef flow) {
     46             e[le].u=u;
     47             e[le].v=v;
     48             e[le].flow=flow;
     49             e[le].next=head[u];
     50             head[u]=le++;
     51         }
     52     } g;
     53 public:
     54     void init(int tn) {///传入点的个数
     55         n=tn;
     56         g.init();
     57     }
     58     void add(int u,int v,typef flow) {
     59         g.add(u,v,flow);
     60         g.add(v,u,0);
     61     }
     62     typef solve(int s,int t) {
     63         bfs(s,t);
     64         flow=top=0;
     65         for(i=0;i<=n;i++) cur[i]=g.head[i];
     66         int u=s;
     67         while(dep[s]<n) {
     68             if(u==t) {
     69                 int temp=inf;
     70                 for(i=0; i<top; i++)
     71                     if(temp>g.e[S[i]].flow) {
     72                         temp=g.e[S[i]].flow;
     73                         inser=i;
     74                     }
     75                 for(i=0; i<top; i++) {
     76                     g.e[S[i]].flow-=temp;
     77                     g.e[S[i]^1].flow+=temp;
     78                 }
     79                 flow+=temp;
     80                 top=inser;
     81                 u=g.e[S[top]].u;
     82             }
     83             if(u!=t&&!gap[dep[u]-1]) break;
     84             for(i=cur[u]; ~i; i=g.e[i].next)
     85                 if(g.e[i].flow&&dep[u]==dep[g.e[i].v]+1)
     86                     break;
     87             if(~i) {
     88                 cur[u]=i;
     89                 S[top++]=i;
     90                 u=g.e[i].v;
     91             } else {
     92                 int sma=n;
     93                 for(i=g.head[u]; ~i; i=g.e[i].next) {
     94                     if(!g.e[i].flow) continue;
     95                     int v=g.e[i].v;
     96                     if(sma>dep[v]) {
     97                         sma=dep[v];
     98                         cur[u]=i;
     99                     }
    100                 }
    101                 --gap[dep[u]];
    102                 dep[u]=sma+1;
    103                 ++gap[dep[u]];
    104                 if(u!=s) u=g.e[S[--top]].u;
    105             }
    106         }
    107         return flow;
    108     }
    109 }sap;
    110 
    111 bool vis[5010];
    112 void dfs(int u,int t) {
    113     if(u==t) return ;
    114     vis[u]=true;
    115     for(int i=sap.g.head[u]; ~i; i=sap.g.e[i].next) {
    116         int v=sap.g.e[i].v;
    117         if(sap.g.e[i].flow&&!vis[v]) {
    118             dfs(v,t);
    119         }
    120     }
    121 }
    122 int main() {
    123     int n,m;
    124     while(~scanf("%d%d",&n,&m)) {
    125         sap.init(n+2);
    126         LL sum=0;
    127         int s=0,t=n+1;
    128         for(int i=1,val; i<=n; i++) {
    129             scanf("%d",&val);
    130             if(val>0) {
    131                 sum+=val;
    132                 sap.add(s,i,val);
    133             } else {
    134                 sap.add(i,t,-val);
    135             }
    136         }
    137         while(m--) {
    138             int u,v;
    139             scanf("%d%d",&u,&v);
    140             sap.add(u,v,inf);
    141         }
    142         LL flow=sap.solve(s,t);
    143         mt(vis,0);
    144         dfs(s,t);
    145         int ans=0;
    146         for(int i=1; i<=n; i++) {
    147             if(vis[i]) ans++;
    148         }
    149         printf("%d %I64d
    ",ans,sum-flow);
    150     }
    151     return 0;
    152 }
    View Code

    end

  • 相关阅读:
    bzoj1002/luogu2144 轮状病毒 (dp)
    bzoj1003/luogu1772 物流运输 (dijkstra+dp)
    bzoj1007/luogu3194 水平可见直线 (单调栈)
    [模板]群论
    http 协议媒体格式
    java加密类支持sha256,md5,HmacSha1,base64
    java逐行读写借助buffereader/bufferwriter
    java 基础io读写字节以及缓存读写字节
    java log4i.properties
    java 迭代器
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3936973.html
Copyright © 2011-2022 走看看