其他分享
首页 > 其他分享> > [八省联考2018] 劈配 (网络流+二分)

[八省联考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 }

 

标签:八省,return,int,flow,mid,limit,2018,L1,联考
来源: https://www.cnblogs.com/guapisolo/p/10651400.html