zoukankan      html  css  js  c++  java
  • [八省联考2018] 劈配 (网络流+二分)

    题目大意:略

    先考虑第一问

    直接跑最大流肯定是不好使的

    考虑动态地进行这个过程

    枚举每个选手,枚举每一等级的志愿

    把选手向当前志愿内的每个导师都连流量为1的边,然后找增广路

    如果找不到增广路,说明在当前等级志愿内并不能找到合法导师,删掉当前状态下选手和导师的所有边,继续枚举下一等级志愿

    如果找到了增广路,说明存在合法导师,跳出。并继续枚举下一个选手

    写个伪代码:

    for 选手1~n

    for 志愿等级1~m

      1.把选手向当前等级志愿内的所有导师连流量为1的边

      2.找不到增广路:删掉所有和导师间的连边

         找到了增广路:跳出

    正确性似乎显然啊

    第二个问怎么搞?

    发现这个问题具有单调性,考虑二分

    验证需要还原加入前mid个选手的图,可持久化网络流?其实在加入每个选手以后都把图存一遍就行了

      1 #include <vector>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #define L1 205
      6 #define N1 410
      7 #define M1 3050
      8 using namespace std;
      9 const int inf=0x3f3f3f3f;
     10 
     11 template <typename _T> void read(_T &ret)
     12 {
     13     ret=0; _T fh=1; char c=getchar();
     14     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
     15     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
     16     ret=ret*fh;
     17 }
     18 
     19 struct Edge{
     20 int to[M1*2],nxt[M1*2],flow[M1*2],head[M1*2],cte;
     21 void ae(int u,int v,int f)
     22 { cte++; to[cte]=v; flow[cte]=f; nxt[cte]=head[u]; head[u]=cte; }
     23 }E,o[L1];
     24 
     25 int n,m,S,T,hd,tl;
     26 int dep[N1],cur[N1],que[N1];
     27 
     28 int bfs(Edge &e)
     29 {
     30     int x,j,v;
     31     memset(dep,-1,(T+1)*4); memcpy(cur,e.head,(T+1)*4);
     32     hd=1,tl=0; que[++tl]=S; dep[S]=0;
     33     while(hd<=tl)
     34     {
     35         x=que[hd++];
     36         for(j=e.head[x];j;j=e.nxt[j])
     37         {
     38             v=e.to[j];
     39             if(dep[v]==-1 && e.flow[j]>0)
     40                 dep[v]=dep[x]+1, que[++tl]=v;
     41         }
     42     }
     43     return dep[T]!=-1;
     44 }
     45 int dfs(Edge &e,int x,int limit)
     46 {
     47     if(x==T||!limit) return limit;
     48     int j,v,flow,ans=0;
     49     for(j=cur[x];j;j=e.nxt[j])
     50     {
     51         v=e.to[j]; cur[x]=j;
     52         if(dep[v]==dep[x]+1 && (flow=dfs(e,v,min(e.flow[j],limit))))
     53         {
     54             e.flow[j]-=flow; limit-=flow;
     55             e.flow[j^1]+=flow; ans+=flow;
     56             if(!limit) break;
     57         }
     58     }
     59     return ans;
     60 }
     61 int Dinic(Edge &e)
     62 {
     63     int mxflow=0;
     64     while(bfs(e)) mxflow+=dfs(e,S,inf);
     65     return mxflow;
     66 }
     67 
     68 vector<int>ccf[L1];
     69 int b[L1],a[L1][L1],want[L1];
     70 
     71 int solve(Edge &e,int x)
     72 {
     73     int i,j,k,now,tmp;
     74     e.ae(S,x,1); e.ae(x,S,0); now=e.cte;
     75     for(i=0;i<=m;i++) ccf[i].clear();
     76     for(i=1;i<=m;i++) ccf[a[x][i]].push_back(i);
     77     for(i=1;i<=m;i++) if(ccf[i].size()>0)
     78     {
     79         for(k=0;k<ccf[i].size();k++)
     80             e.ae(x,ccf[i][k]+n,1), e.ae(ccf[i][k]+n,x,0);
     81         tmp=Dinic(e);
     82         if(!tmp)
     83         {
     84             for(k=ccf[i].size()-1;k>=0;k--)
     85                 e.head[x]=e.nxt[e.head[x]], e.head[ccf[i][k]+n]=e.nxt[e.head[ccf[i][k]+n]]; 
     86             e.cte=now; continue;
     87         }
     88         break;
     89     }
     90     memcpy(&o[x],&e,sizeof(o[x]));
     91     return i;
     92 }
     93 
     94 int id[N1],real[N1],happy[N1];
     95 
     96 int check(int limit,int x)
     97 {
     98     int i,j,ans=0;
     99     memcpy(&E,&o[limit-1],sizeof(E));
    100     E.ae(S,x,1); E.ae(x,S,0);
    101     for(i=1;i<=m;i++) if(0<a[x][i] && a[x][i]<=want[x]) E.ae(x,i+n,1), E.ae(i+n,x,0);
    102     ans=Dinic(E);
    103     if(ans>0) return 1; else return 0;
    104 }
    105 void init(); 
    106 
    107 void _Main_()
    108 {
    109     init();
    110     int i,j,k,tmp,x,mid; E.cte=1;
    111     scanf("%d%d",&n,&m); S=0; T=n+m+1;
    112     for(i=1;i<=m;i++) read(b[i]), E.ae(i+n,T,b[i]), E.ae(T,i+n,0);
    113     for(i=1;i<=n;i++) for(j=1;j<=m;j++) read(a[i][j]);
    114     for(i=1;i<=n;i++) read(want[i]);
    115     memcpy(&o[0],&E,sizeof(o[0]));
    116     for(i=1;i<=n;i++)
    117     {
    118         real[i]=solve(E,i); 
    119     }
    120     for(i=1;i<=n;i++) printf("%d ",real[i]); puts("");
    121     int l,r;
    122     for(i=1;i<=n;i++)
    123     {
    124         if(real[i]<=want[i]){ happy[i]=0; continue; }
    125         l=1; r=i-1; happy[i]=i;
    126         while(l<=r)
    127         {
    128             mid=(l+r)>>1;
    129             if(check(mid,i)) happy[i]=i-mid, l=mid+1;
    130             else r=mid-1;
    131         }
    132     }
    133     for(i=1;i<=n;i++) printf("%d ",happy[i]); puts("");
    134 }
    135 
    136 int TT,CC;
    137 int main()
    138 {
    139     scanf("%d%d",&TT,&CC);
    140     while(TT--) _Main_();
    141     return 0;
    142 }
    143 
    144 void init()
    145 {
    146     memset(id,0,sizeof(id)); memset(real,0,sizeof(real)); memset(happy,0,sizeof(happy)); 
    147     memset(&E,0,sizeof(E)); memset(o,0,sizeof(o));
    148 }
  • 相关阅读:
    JavaScript ECMAScript 2015 (ES6) 和 ECMAScript 2016 (ES7) 新特性速查
    Sass中文文档
    TypeScript手册中文版
    敏捷:什么是用户故事(User Story)
    Repeater为空时显示“暂无数据”,很方便实用方法
    jquery之css()改变字体大小,颜色,背景色
    七牛 在线管理 v0.1
    clion idea jetbrain windows下搞c/c++
    amazeui 搜索 动态
    命令行启动软件
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10651400.html
Copyright © 2011-2022 走看看