• poj 2125(最小割)


    题目链接:http://poj.org/problem?id=2125

    思路:将最小点权覆盖转化为最小割模型,于是拆点建图,将点i拆成i,i+n,其中vs与i相连,边容量为w[i]-,i+n与vt相连,边容量为w[i]+,如果i,j有边相连,则i与j+n连边inf.从而跑最大流求解。对于输出解决放案,我们可以在残余网络中进行dfs,从vs出发,对于那些i<=n没有遍历到的点,说明被取走了,输出‘-’,对于那些i>n遍历到的点,说明之前有j->i的边(j<=n),vs->j不是最小割中的边,i是最小割中的点,输出‘+’。

    copy一张图:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 #define MAXN 222
      8 #define MAXM 2222222
      9 #define inf 1<<30
     10 
     11 struct Edge{
     12     int v,cap,next;
     13 }edge[MAXM];
     14 
     15 int n,m,NE,vs,vt,NV;
     16 int head[MAXN];
     17 
     18 void Insert(int u,int v,int cap)
     19 {
     20     edge[NE].v=v;
     21     edge[NE].cap=cap;
     22     edge[NE].next=head[u];
     23     head[u]=NE++;
     24 
     25     edge[NE].v=u;
     26     edge[NE].cap=0;
     27     edge[NE].next=head[v];
     28     head[v]=NE++;
     29 }
     30 
     31 int from[MAXN],to[MAXN];
     32 bool map[MAXN][MAXN];
     33 
     34 void Build()
     35 {
     36     NE=0;
     37     memset(head,-1,sizeof(head));
     38     vs=0,vt=2*n+1,NV=2*n+2;
     39     for(int i=1;i<=n;i++){
     40         Insert(vs,i,to[i]);
     41         Insert(i+n,vt,from[i]);
     42         for(int j=1;j<=n;j++){
     43             if(map[i][j])Insert(i,j+n,inf);
     44         }
     45     }
     46 }
     47 
     48 int level[MAXN],gap[MAXN];
     49 void bfs(int vt)
     50 {
     51     memset(level,-1,sizeof(level));
     52     memset(gap,0,sizeof(gap));
     53     level[vt]=0;
     54     gap[level[vt]]++;
     55     queue<int>que;
     56     que.push(vt);
     57     while(!que.empty()){
     58         int u=que.front();
     59         que.pop();
     60         for(int i=head[u];i!=-1;i=edge[i].next){
     61             int v=edge[i].v;
     62             if(level[v]<0){
     63                 level[v]=level[u]+1;
     64                 gap[level[v]]++;
     65                 que.push(v);
     66             }
     67         }
     68     }
     69 }
     70 
     71 int cur[MAXN],pre[MAXN];
     72 
     73 int SAP(int vs,int vt)
     74 {
     75     bfs(vt);
     76     memset(pre,-1,sizeof(pre));
     77     memcpy(cur,head,sizeof(head));
     78     int maxflow=0,aug=inf;
     79     int u=pre[vs]=vs;
     80     gap[0]=NV;
     81     while(level[vs]<NV){
     82         bool flag=false;
     83         for(int &i=cur[u];i!=-1;i=edge[i].next){
     84             int v=edge[i].v;
     85             if(edge[i].cap>0&&level[u]==level[v]+1){
     86                 flag=true;
     87                 pre[v]=u;
     88                 u=v;
     89                 aug=min(aug,edge[i].cap);
     90                 if(v==vt){
     91                     maxflow+=aug;
     92                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
     93                         edge[cur[u]].cap-=aug;
     94                         edge[cur[u]^1].cap+=aug;
     95                     }
     96                     aug=inf;
     97                 }
     98                 break;
     99             }
    100         }
    101         if(flag)continue;
    102         int minlevel=NV;
    103         for(int i=head[u];i!=-1;i=edge[i].next){
    104             int v=edge[i].v;
    105             if(edge[i].cap>0&&level[v]<minlevel){
    106                 minlevel=level[v];
    107                 cur[u]=i;
    108             }
    109         }
    110         if(--gap[level[u]]==0)break;
    111         level[u]=minlevel+1;
    112         gap[level[u]]++;
    113         u=pre[u];
    114     }
    115     return maxflow;
    116 }
    117 
    118 bool mark[MAXN];
    119 void dfs(int u)
    120 {
    121     mark[u]=true;
    122     for(int i=head[u];i!=-1;i=edge[i].next){
    123         int v=edge[i].v;
    124         if(!mark[v]&&edge[i].cap>0)dfs(v);
    125     }
    126 }
    127 
    128 
    129 int main()
    130 {
    131 //   freopen("1.txt","r",stdin);
    132     int u,v,cnt;
    133     while(~scanf("%d%d",&n,&m)){
    134         for(int i=1;i<=n;i++)scanf("%d",&from[i]);
    135         for(int i=1;i<=n;i++)scanf("%d",&to[i]);
    136         memset(map,false,sizeof(map));
    137         while(m--){
    138             scanf("%d%d",&u,&v);
    139             map[u][v]=true;
    140         }
    141         Build();
    142         printf("%d
    ",SAP(vs,vt));
    143         memset(mark,false,sizeof(mark));
    144         dfs(vs);
    145         cnt=0;
    146         for(int i=1;i<=2*n;i++){
    147             if(!mark[i]&&i<=n)cnt++;
    148             else if(mark[i]&&i>n)cnt++;
    149         }
    150         printf("%d
    ",cnt);
    151         for(int i=1;i<=2*n;i++){
    152             if(!mark[i]&&i<=n)printf("%d -
    ",i);
    153             else if(mark[i]&&i>n)printf("%d +
    ",i-n);
    154         }
    155     }
    156     return 0;
    157 }
    View Code
  • 相关阅读:
    MySQL:数据库优化,看这篇就够了
    不使用synchronized和lock,如何实现一个线程安全的单例
    理解Spring:IOC的原理及手动实现
    终于放弃了单调的swagger-ui了,选择了这款神器—knife4j
    TP5.0.24 验证器内置规则中max 如果输入中文 验证长度错误的问题
    laravel 5.5 api接口开发:JWT安装+实现API token 认证
    homestead 代码与本地代码不同步的解决方法
    laravel 5.5 api接口开发: 安装dingo/api
    php base_decode 函数将base64编码转换图片遇到的问题
    thinkphp 5.0 部署新网空间隐藏index.php入口
  • 原文地址:https://www.cnblogs.com/wally/p/3277775.html
Copyright © 2020-2023  润新知