http://acm.hdu.edu.cn/showproblem.php?pid=3605
注意n的范围是100000,m的范围是10,所以最多的情况是合并成2^10=1024个n
先用map合并点,然后源点到n的容量设为p(表示这种点的数量),m到汇点的容量按题设
然后求最大流即可
PS:如果不合并点会TLE
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #include<string> 6 #include<cmath> 7 #include<set> 8 #include<list> 9 #include<map> 10 #include<iterator> 11 #include<cstdlib> 12 #include<vector> 13 #include<queue> 14 #include<stack> 15 #include<algorithm> 16 #include<functional> 17 using namespace std; 18 typedef long long LL; 19 #define ROUND(x) round(x) 20 #define FLOOR(x) floor(x) 21 #define CEIL(x) ceil(x) 22 const int maxn=1200; 23 const int maxm=200010; 24 const int inf=0x3f3f3f3f; 25 const LL inf64=0x3f3f3f3f3f3f3f3fLL; 26 const double INF=1e30; 27 const double eps=1e-6; 28 29 /** 30 *最大流最小割:加各种优化的Dinic算法($O(V^2E)$) 31 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇) 32 *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流) 33 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找 34 */ 35 //const int maxn=0; 36 //const int maxm=0; 37 //const int inf=0x3f3f3f3f; 38 struct Edge 39 { 40 int u,v; 41 int cap,flow; 42 int next; 43 } edge[maxm]; 44 int head[maxn],edgeNum;//需初始化 45 int n,m,d[maxn],cur[maxn]; 46 int st,ed; 47 bool vis[maxn]; 48 void addSubEdge(int u,int v,int cap,int flow) 49 { 50 edge[edgeNum].u=u; 51 edge[edgeNum].v=v; 52 edge[edgeNum].cap=cap; 53 edge[edgeNum].flow=flow; 54 edge[edgeNum].next=head[u]; 55 head[u]=edgeNum++; 56 cur[u]=head[u]; 57 } 58 void addEdge(int u,int v,int cap) 59 { 60 addSubEdge(u,v,cap,0); 61 addSubEdge(v,u,0,0);//注意加反向0 边 62 } 63 bool BFS() 64 { 65 queue<int> Q; 66 memset(vis, 0, sizeof(vis)); 67 Q.push(st); 68 d[st]=0; 69 vis[st]=1; 70 while (!Q.empty()) 71 { 72 int u=Q.front(); 73 Q.pop(); 74 for(int i=head[u]; i!=-1; i=edge[i].next) 75 { 76 int v=edge[i].v; 77 int w=edge[i].cap-edge[i].flow; 78 if(w>0 && !vis[v]) 79 { 80 vis[v]=1; 81 Q.push(v); 82 d[v]=d[u]+1; 83 if(v==ed) return 1; 84 } 85 } 86 } 87 return false; 88 } 89 int Aug(int u, int a) 90 { 91 if (u==ed) return a; 92 int aug=0, delta; 93 for(int &i=cur[u]; i!=-1; i=edge[i].next) 94 { 95 int v=edge[i].v; 96 int w=edge[i].cap-edge[i].flow; 97 if (w>0 && d[v]==d[u]+1) 98 { 99 delta = Aug(v, min(a,w)); 100 if (delta) 101 { 102 edge[i].flow += delta; 103 edge[i^1].flow -= delta; 104 aug += delta; 105 if (!(a-=delta)) break; 106 } 107 } 108 } 109 if (!aug) d[u]=-1; 110 return aug; 111 } 112 int Dinic(int NdFlow) 113 { 114 int flow=0; 115 while (BFS()) 116 { 117 memcpy(cur,head,sizeof(int)*(n+1)); 118 flow += Aug(st,inf); 119 /*如果超过指定流量就return 掉*/ 120 if(NdFlow==inf) continue; 121 if(flow > NdFlow) break; 122 } 123 return flow; 124 } 125 126 map<string,int> mp; 127 map<string,int>::iterator ite; 128 int N,M; 129 char strx[110]; 130 int num[20]; 131 void init() 132 { 133 memset(head,-1,sizeof(head)); 134 edgeNum=0; 135 mp.clear(); 136 } 137 void input() 138 { 139 if(scanf("%d%d",&N,&M)==EOF) exit(0); 140 getchar(); 141 for(int i=0;i<N;i++) 142 { 143 gets(strx); 144 string str=strx; 145 mp[str]++; 146 } 147 for(int i=0;i<M;i++) scanf("%d",&num[i]); 148 } 149 void build() 150 { 151 n=mp.size()+M+2; 152 st=0,ed=mp.size()+M+1; 153 int i; 154 for(ite=mp.begin(),i=1;ite!=mp.end();ite++,i++) 155 { 156 addEdge(st,i,ite->second); 157 int m=1; 158 for(int j=0;j<ite->first.size();j++) 159 { 160 if(ite->first[j]=='1') 161 { 162 addEdge(i,mp.size()+m,ite->second); 163 } 164 if(ite->first[j]=='0'||ite->first[j]=='1') 165 { 166 m++; 167 } 168 } 169 } 170 for(i=mp.size()+1;i<=mp.size()+M;i++) 171 { 172 addEdge(i,ed,num[i-(mp.size()+1)]); 173 } 174 } 175 void solve() 176 { 177 build(); 178 if(Dinic(inf)==N) puts("YES"); 179 else puts("NO"); 180 // printf("%d ",Dinic(inf)); 181 } 182 void output() 183 { 184 // 185 } 186 int main() 187 { 188 // std::ios_base::sync_with_stdio(false); 189 // freopen("in.cpp","r",stdin); 190 while(1) 191 { 192 init(); 193 input(); 194 solve(); 195 output(); 196 } 197 return 0; 198 }