zoukankan      html  css  js  c++  java
  • LA 3268 号码簿分组(最大流+二分)

    https://vjudge.net/problem/UVALive-3268

    题意:

    有n个人和m个组。一个人可能属于很多组。现在请你从某些组中去掉几个人,使得每个人只属于一个组,并使得人数最多的组中人员数目为最小值。

    思路:
    建立超级源汇点,源点和每个人相连,容量为1,说明每个人最多只能在一个组中。每个人和可以属于的组相连,容量为1。接下来枚举组的最大容量值,将每组和汇点相连,容量为枚举值,二分跑最大流即可。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 2000 + 5;
     17 
     18 vector<int> g[maxn];
     19 
     20 struct Edge
     21 {
     22     int from,to,cap,flow;
     23     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     24 };
     25 
     26 struct Dinic
     27 {
     28     int n,m,s,t;
     29     vector<Edge> edges;
     30     vector<int> G[maxn];
     31     bool vis[maxn];
     32     int cur[maxn];
     33     int d[maxn];
     34 
     35     void init(int n)
     36     {
     37         this->n=n;
     38         for(int i=0;i<n;++i) G[i].clear();
     39         edges.clear();
     40     }
     41 
     42     void AddEdge(int from,int to,int cap)
     43     {
     44         edges.push_back( Edge(from,to,cap,0) );
     45         edges.push_back( Edge(to,from,0,0) );
     46         m=edges.size();
     47         G[from].push_back(m-2);
     48         G[to].push_back(m-1);
     49     }
     50 
     51     bool BFS()
     52     {
     53         queue<int> Q;
     54         memset(vis,0,sizeof(vis));
     55         vis[s]=true;
     56         d[s]=0;
     57         Q.push(s);
     58         while(!Q.empty())
     59         {
     60             int x=Q.front(); Q.pop();
     61             for(int i=0;i<G[x].size();++i)
     62             {
     63                 Edge& e=edges[G[x][i]];
     64                 if(!vis[e.to] && e.cap>e.flow)
     65                 {
     66                     vis[e.to]=true;
     67                     d[e.to]=d[x]+1;
     68                     Q.push(e.to);
     69                 }
     70             }
     71         }
     72         return vis[t];
     73     }
     74 
     75     int DFS(int x,int a)
     76     {
     77         if(x==t || a==0) return a;
     78         int flow=0, f;
     79         for(int &i=cur[x];i<G[x].size();++i)
     80         {
     81             Edge &e=edges[G[x][i]];
     82             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     83             {
     84                 e.flow +=f;
     85                 edges[G[x][i]^1].flow -=f;
     86                 flow +=f;
     87                 a -=f;
     88                 if(a==0) break;
     89             }
     90         }
     91         return flow;
     92     }
     93 
     94     int Maxflow(int s,int t)
     95     {
     96         this->s=s; this->t=t;
     97         int flow=0;
     98         while(BFS())
     99         {
    100             memset(cur,0,sizeof(cur));
    101             flow +=DFS(s,INF);
    102         }
    103         return flow;
    104     }
    105 }DC;
    106 
    107 int n, m;
    108 int src, dst;
    109 
    110 bool solve(int x)
    111 {
    112     DC.init(dst+1);
    113     for(int i=1;i<=n;i++)
    114     {
    115         DC.AddEdge(src,i,1);
    116         for(int j=0;j<g[i].size();j++)
    117         {
    118             DC.AddEdge(i,g[i][j]+n+1,1);
    119         }
    120     }
    121     for(int i=1;i<=m;i++)
    122         DC.AddEdge(i+n,dst,x);
    123 
    124     if(DC.Maxflow(src,dst)==n)  return true;
    125     else return false;
    126 }
    127 
    128 int main()
    129 {
    130     //freopen("in.txt","r",stdin);
    131     while(~scanf("%d%d",&n,&m) && (n+m))
    132     {
    133         for(int i=1;i<=n;i++)  g[i].clear();
    134         src=0, dst=n+m+1;
    135 
    136         for(int i=1;i<=n;i++)
    137         {
    138             char name[20]; char c; int x;
    139 
    140             cin>>name;
    141             while(~scanf("%d%c",&x,&c))
    142             {
    143                 g[i].push_back(x);
    144                 if(c=='
    ')  break;
    145             }
    146         }
    147 
    148         int ans=0;
    149         int L=0,R=n;
    150         while(L<=R)
    151         {
    152             int mid=(L+R)/2;
    153             if(solve(mid))  {ans=mid;R=mid-1;}
    154             else L=mid+1;
    155         }
    156         printf("%d
    ",ans);
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    Oracle建立表空间和用户
    fscanf()函数具体解释
    三层架构(我的理解及具体分析)
    ListView嵌套ListView优化
    Android xml 解析
    玩转Web之servlet(三)---一张图看懂B/S架构
    jquery.scrollTo-min.js
    C#中MessageBox使用方法大全(附效果图)
    hdu 1882 Strange Billboard(位运算+枚举)
    MySQL 通配符学习小结
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7262091.html
Copyright © 2011-2022 走看看