链接:点击打开链接
题意:在一个会议室里有n种插座,每种插座一个,每个插座只能插一种以及一个电器(或者适配器),有m个电器,每个电器有一个插头需要插在相应一种插座上,有k种适配器,每种适配器可以有无限多数量,每种适配器(a, b)可以把b类插座变为a类插座,问最后有多少个电器无法使用
代码:
#include <set> #include <queue> #include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> using namespace std; const int INF=0x3f3f3f3f; struct node{ int u,v,cap; node(){} node(int u,int v,int cap):u(u),v(v),cap(cap){} }es[505*505]; int R,S,T,K; int dis[505],iter[505]; char name[505][50]; vector<int> tab[505]; void addedge(int u, int v, int cap){ tab[u].push_back(R); es[R++]=node(u,v,cap); tab[v].push_back(R); es[R++]=node(v,u,0); } int bfs(){ int i,h; queue<int> q; q.push(S); memset(dis,INF,sizeof(dis)); dis[S]=0; while(q.size()){ h=q.front(); q.pop(); for(i=0;i<tab[h].size();i++){ node &e=es[tab[h][i]]; if(e.cap>0&&dis[e.v]==INF){ dis[e.v]=dis[h]+1; q.push(e.v); } } } return dis[T]<INF; } int dfs(int x,int maxflow){ int flow; if(x==T) return maxflow; for(int &i=iter[x];i<tab[x].size();i++){ node &e=es[tab[x][i]]; if(dis[e.v]==dis[x]+1&&e.cap>0){ flow=dfs(e.v,min(maxflow,e.cap)); if(flow){ e.cap-=flow; es[tab[x][i]^1].cap+=flow; return flow; } } } return 0; } int judge(char str[]){ int i; if(K==0){ strcpy(name[1],str); K=1; return 1; } for(i=1;i<=K;i++) if(strcmp(name[i],str)==0) return i; //判断是否出现过 K++; strcpy(name[K],str); return K; } //直接返回当前串的编号 int dinic(){ int ans,flow; ans=0; while(bfs()){ memset(iter,0,sizeof(iter)); while(flow=dfs(S,INF)) ans+=flow; } return ans; } //网络流模板 int main(){ int n,i,j,tmp; char s[50],str[50]; while(scanf("%d",&n)!=EOF){ R=S=K=0,T=500; //不知道节点个数时可以将汇点设的大一点 memset(name,0,sizeof(name)); for(i=0;i<=T;i++) tab[i].clear(); scanf("%d",&n); for(i=0;i<n;i++){ scanf("%s",s); addedge(S,judge(s),1); //插头与源点相连 } scanf("%d",&n); for(i=0;i<n;i++){ scanf("%s%s",s,str); addedge(judge(s),T,1); //用电器与汇点相连 addedge(judge(str),judge(s),1); //插座和用电器相连 } tmp=n; scanf("%d",&n); for(i=0;i<n;i++){ scanf("%s%s",s,str); addedge(judge(str),judge(s),INF); //可以转换的换位容量是INF的边 } printf("%d\n",tmp-dinic()); } return 0; }