link:http://acm.upc.edu.cn/problem.php?id=2161
这题的大题题意是给你N个多面体,每个多面体的每个面都有字母,然后告诉你几个单词,问你能拼出几个单词。
从这道题意不难看出这每个多面体只能每次提供一个字母,也就是说每个多面体预期所带的字母之间所能提供的流量为1 ,不难看出是个二分图,当时用的DFS果断超时,然后想到二分匹配时觉得二分匹配不熟,写了个EK最大流也超市。。。后来回到宿舍敲了一个DINIC果断88ms啊!刚才写了个二分匹配还是超市,不过QC他们的二分过了不知道为什么。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <stdio.h> #include <iostream> #include <queue> #include <string.h> #include <vector> #define maxn 1050 using namespace std; int m,n; struct edge { int u,v,cap,flow; }; vector<edge>edges; vector<edge>ed; vector<int>g[maxn],G[maxn]; void addedge(int u,int v,int cap,int flow) { edges.push_back((edge){u,v,cap,flow}); edges.push_back((edge){v,u,0,0}); int m; m = edges.size(); g[u].push_back(m-2); g[v].push_back(m-1); } void init(int n) { int i; for(i = 0;i <= n;i++) { g[i].clear(); } edges.clear(); } int vis[maxn],dis[maxn],cur[maxn]; int bfs(int s,int t,int n) { memset(vis,0,sizeof(vis)); queue<int>q; q.push(s); dis[s] = 0; vis[s] = 1; while(!q.empty()) { int u,v; u = q.front(); q.pop(); for(int i = 0;i < g[u].size();i++) { edge &e = edges[g[u][i]]; v = e.v; if(!vis[v] && e.cap-e.flow > 0) { vis[v] = 1; dis[v] = dis[u] +1; q.push(v); } } } return vis[t]; } int dfs(int u,int a,int t) { if(u == t || a == 0) return a; int v; int flow = 0,f; for(int& i = cur[u]; i < g[u].size();i++) { edge &e = edges[g[u][i]]; v = e.v; if(dis[u]+1 == dis[v] &&(f = dfs(v,min(a,e.cap-e.flow),t))) { e.flow += f; edges[g[u][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int maxflow(int s,int t) { int flow = 0; while(bfs(s,t,t)) { memset(cur,0,sizeof(cur)); flow+=dfs(s,1000050,t); } return flow; } int main() { int i,j; int t; while(~scanf("%d",&t)) { while(t--) { scanf("%d %d",&m,&n); init(100+m); int u,v; int word[30]; for(u = 1;u <= m;u++) { addedge(0,u,1,0); char str[5005]; scanf("%s",str); memset(word,0,sizeof(word)); for(i = 0;str[i] != '\0';i++) { if(str[i] >= 'a' && str[i] <= 'z') str[i]-=32; v = str[i]-'A'; if(!word[v]) addedge(u,m+v+1,1,0); word[v] = 1; } } int ans = 0; ed = edges; for(i = 0;i <= m+28;i++) G[i] = g[i]; for(u = 1;u <= n;u++) { edges = ed; memset(word,0,sizeof(word)); for(i = 0;i <= m+28;i++) g[i] = G[i]; char str[5005]; scanf("%s",str); int len,res; len = strlen(str); for(i = 0;i < len;i++) { if(str[i] >= 'a' && str[i]<='z') str[i] -= 32; v = str[i]-'A'; word[v]++; } for(i = 0;i <= 25;i++) { if(word[i]) addedge(m+i+1,m+27,word[i],0); } res = maxflow(0,m+26+1); if(res >= len) ans++;//,cout<<"yes"<<endl; } printf("%d\n",ans); } } return 0; }