[loj2477]劈配

考虑依次选择每一位考生,设当前选到第$i+1$位,前i个分别为$p1,p2,……pi$(注意:这里只确定了导师的志愿编号),然后枚举第$p_{i+1}$,通过网络流建图+判定,复杂度为$o(nm*f(n+m,cn))$($f(n,m)$表示点数为n、边数为m的网络流),无法通过
考虑优化,由于网络流可以先任意流,那么直接在之前的残余网络上加上第k份志愿并判断能否联通即可,复杂度$o(cn^{2}m)$
第二个问题类似,存储下每一次跑完后的残余网络,然后从下往上枚举其排名(志愿为si及其以上的)并建图,复杂度同样为$o(cn^{2}m)$
 
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 205
 4 struct ji{
 5     int nex,to,len;
 6 }edge[30*N],e[N][30*N];
 7 vector<int>v[N][N];
 8 int E,t,n,m,x,EE[N],head[N<<1],vis[N<<1],h[N][N<<1];
 9 void add(int x,int y,int z){
10     edge[E].nex=head[x];
11     edge[E].to=y;
12     edge[E].len=z;
13     head[x]=E++;
14 }
15 bool dfs(int k){
16     if (k==n+m+1)return 1;
17     if (vis[k])return 0;
18     vis[k]=1;
19     for(int i=head[k];i!=-1;i=edge[i].nex)
20         if ((edge[i].len)&&(dfs(edge[i].to))){
21             edge[i].len--;
22             edge[i^1].len++;
23             return 1;
24         }
25     return 0;
26 }
27 int main(){
28     scanf("%d%*d",&t);
29     while (t--){
30         scanf("%d%d",&n,&m);
31         E=0;
32         memset(head,-1,sizeof(head));
33         for(int i=1;i<=n;i++)
34             for(int j=1;j<=m;j++)v[i][j].clear();
35         for(int i=1;i<=m;i++){
36             scanf("%d",&x);
37             add(i+n,n+m+1,x);
38             add(n+m+1,i+n,0);
39         }
40         for(int i=1;i<=n;i++)
41             for(int j=1;j<=m;j++){
42                 scanf("%d",&x);
43                 if (x)v[i][x].push_back(j);
44             }
45         EE[0]=E;
46         memcpy(h[0],head,sizeof(head));
47         memcpy(e[0],edge,sizeof(edge));
48         for(int i=1;i<=n;i++){
49             bool flag=0;
50             EE[i]=E;
51             memcpy(h[i],head,sizeof(head));
52             memcpy(e[i],edge,sizeof(edge));
53             for(int j=1;j<=m;j++){
54                 E=EE[i];
55                 memset(vis,0,sizeof(vis)); 
56                 memcpy(head,h[i],sizeof(head));
57                 memcpy(edge,e[i],sizeof(edge));
58                 for(int k=0;k<v[i][j].size();k++){
59                     add(i,v[i][j][k]+n,1);
60                     add(v[i][j][k]+n,i,0);
61                 }
62                 if (dfs(i)){
63                     flag=1;
64                     printf("%d ",j);
65                     break;
66                 }
67             }
68             if (!flag)printf("%d ",m+1);
69             EE[i]=E;
70             memcpy(h[i],head,sizeof(head));
71             memcpy(e[i],edge,sizeof(edge));
72         }
73         printf("
");
74         for(int i=1;i<=n;i++){
75             scanf("%d",&x);
76             bool flag=0;
77             for(int j=i;j;j--){
78                 E=EE[j-1];
79                 memset(vis,0,sizeof(vis)); 
80                 memcpy(head,h[j-1],sizeof(head));
81                 memcpy(edge,e[j-1],sizeof(edge));
82                 for(int k=1;k<=x;k++)
83                     for(int l=0;l<v[i][k].size();l++){
84                         add(i,v[i][k][l]+n,1);
85                         add(v[i][k][l]+n,i,0);
86                     }
87                 if (dfs(i)){
88                     flag=1;
89                     printf("%d ",i-j);
90                     break;
91                 }
92             }
93             if (!flag)printf("%d ",i);
94         }
95         printf("
");
96     }
97 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/12932505.html