这题的做法非常直观,却又非常不直观
先容许我吐一下槽吧~作者你的英语是读到火星上去了喵?
题目大体是说人类要移民,然后有 n 个人, m 个星球
每个人都有 m 个 0 、 1 数码表示他能否移民到该星球,每个星球有个最大人口容量
问是否有方案移民该 n 个人
乍一看很水,但是看看 n 的数据范围真是太感动人心了,有种这尼玛更本不是网络流的感脚——
但是 m 的范围只有 10 !直觉告诉我似乎可以动手脚的样子喵?
状压!因为不需要输出方案,所以两个可移民方案相同的人完全可以视为同一人
然后点就被压到了 1024 以内,妥妥地过掉了~
我才不会说我连边连错害我调了半小时呢喵
1 #include <cstdio> 2 #include <cstring> 3 #define min(x, y) ((x)<(y) ? (x):(y)) 4 const int inf=0x7FFFFFFF; 5 const int sizeOfPoint=10050; 6 const int sizeOfEdge=500050; 7 8 int n, m, t; 9 int S, T; 10 int f[sizeOfPoint], a[sizeOfPoint]; 11 12 struct edge {int point, flow; edge * next, * pair;}; 13 edge memory[sizeOfEdge], * port=memory; 14 edge * e[sizeOfPoint]; 15 inline void clear() {port=memory; memset(e, 0, sizeof e); t=0; memset(f, 0, sizeof f);} 16 inline edge * newedge(int point, int flow, edge * next) {edge * ret=port++; ret->point=point; ret->flow=flow; ret->next=next; ret->pair=NULL; return ret;} 17 inline void build(int u, int v, int f) {e[u]=newedge(v, f, e[u]); e[v]=newedge(u, 0, e[v]); e[u]->pair=e[v]; e[v]->pair=e[u];} 18 int h[sizeOfPoint]; 19 inline bool bfs(); 20 inline int aug(); 21 inline int dinic(); 22 23 int main() 24 { 25 int x, state; 26 27 while (scanf("%d %d", &n, &m)!=EOF) 28 { 29 clear(); 30 for (int i=1;i<=n;i++) 31 { 32 state=0; 33 for (int j=0;j<m;j++) 34 { 35 scanf("%d", &x); 36 state|=x<<j; 37 } 38 if (!f[state]++) a[++t]=state; 39 } 40 S=0; T=t+m+1; 41 for (int i=1;i<=t;i++) 42 { 43 build(S, i, f[a[i]]); 44 for (int j=0;j<m;j++) if ((a[i]>>j)&1) 45 build(i, t+j+1, f[a[i]]); 46 } 47 for (int i=1;i<=m;i++) 48 { 49 scanf("%d", &x); 50 build(t+i, T, x); 51 } 52 53 if (dinic()==n) printf("YES "); 54 else printf("NO "); 55 } 56 57 return 0; 58 } 59 inline bool bfs() 60 { 61 static int q[sizeOfPoint]; 62 int l=0, r=0; 63 memset(h, 0xFF, sizeof h); h[T]=0; 64 for (q[r++]=T;l<r;l++) 65 { 66 int u=q[l]; 67 for (edge * i=e[u];i;i=i->next) if (i->pair->flow && h[i->point]==-1) 68 h[q[r++]=i->point]=h[u]+1; 69 } 70 return h[S]>=0; 71 } 72 inline int aug() 73 { 74 static edge * t[sizeOfPoint], * path[sizeOfPoint]; 75 static int aug[sizeOfPoint]; 76 int flow=0; 77 78 memcpy(t, e, sizeof e); 79 memset(path, 0, sizeof path); 80 memset(aug, 0, sizeof aug); 81 aug[S]=inf; 82 for (int u=S; ; ) 83 { 84 if (u==T) 85 { 86 flow+=aug[T]; 87 for (edge * i=path[T];i;i=path[i->point]) 88 { 89 i->pair->flow-=aug[T], i->flow+=aug[T]; 90 aug[i->point]-=aug[T]; 91 if (!aug[i->point]) h[i->point]=-1; 92 } 93 u=S; 94 } 95 96 edge *& i=t[u]; 97 for ( ;i && (!i->flow || h[u]!=h[i->point]+1);i=i->next); 98 if (i) 99 { 100 path[i->point]=i->pair; aug[i->point]=min(aug[u], i->flow); 101 u=i->point; i=i->next; 102 } 103 else 104 { 105 if (u==S) break; 106 u=path[u]->point; 107 } 108 } 109 110 return flow; 111 } 112 inline int dinic() 113 { 114 int ret=0, flow; 115 while (bfs()) 116 while (flow=aug()) 117 ret+=flow; 118 return ret; 119 }