思路:设一个超源和超汇,分别连向用电器和插座,那么n个插座就要和汇点相连,所以汇点设的尽可能的大。
m个用电器和插头,就要连在一起,且超源与用电器相连,(以上都是一一对应cap为1),最后适配器之间相连,因为适配器有无数个所以cap为inf;然后一边最大流即可。(PS:在二分匹配中也有此题,直接对插头进行编号并匹配)
网络流:
#include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<iostream> #include<queue> #define inf 0x3f3f3f3f #define MAX 800 using namespace std; int l[10000],st,e,sum; char s[110],p[110],q[110],q1[110][110]; int Map[1100][1100],qu[100000]; int bfs(){ memset(l,-1,sizeof(l)); l[st]=0; int fr,en; fr=en=0; qu[fr++]=st; while(fr>en){ int v=qu[en++]; for(int i=0;i<=e;i++){ if(Map[v][i]&&l[i]==-1){ l[i]=l[v]+1; qu[fr++]=i; } } } return l[e]!=-1; } int dfs(int x,int f){ if(x==e||!f) return f; int tmp=0,a; for(int i=0;i<=e;i++){ if(Map[x][i]&&l[i]==l[x]+1){ a=dfs(i,min(Map[x][i],f-tmp) ); Map[x][i]-=a; Map[i][x]+=a; tmp+=a; if(tmp==f)break; } } if(!tmp) l[x]=-1; return tmp; } int main() { int n,m,i,j,k; while(~scanf("%d",&n)){ memset(Map,0,sizeof(Map)); st=0;e=MAX,sum=0; map<string,int>mp; mp.clear(); for(i=0;i<n;i++){ scanf("%s",s); if(!mp[s]) mp[s]=++sum; Map[mp[s] ][e]=1; } scanf("%d",&m); for(i=0;i<m;i++){ scanf("%s%s",p,q); if(!mp[p]) mp[p]=++sum; Map[st][mp[p] ]=1; if(!mp[q]) mp[q]=++sum; Map[mp[p] ][mp[q] ]=1; } scanf("%d",&k); for(i=0;i<k;i++){ scanf("%s%s",p,q); if(!mp[p]) mp[p]=++sum; if(!mp[q]) mp[q]=++sum; Map[mp[p] ][mp[q]]=inf; } int ans=0; while(bfs()) ans+=dfs(st,inf); printf("%d\n",m-ans); } return 0; }
二分图+传递闭包(注意在传递闭包之前自己和自己也是联通的):
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<algorithm> using namespace std; int n,m,cro[1000],s,re[1000],gs[1000]; bool Map[1000][1000],use[1000]; char a[1000],b[1000]; int DFS(int v) { for(int i=1; i<=n; i++) { if(!use[re[i] ]&&Map[gs[v] ][re[i] ]) { use[re[i] ]=true; if(cro[re[i] ]==-1||DFS(cro[re[i] ] )) { cro[re[i] ]=v; return 1; } } } return 0; } void Floyd() { for(int k=1; k<s; k++) { for(int i=1; i<s; i++) { for(int j=1; j<s; j++) { if(Map[i][k]&&Map[k][j]) Map[i][j]=true; } } } } int main() { int i,j,k; while(~scanf("%d",&n)) { s=1; memset(Map,false,sizeof(Map)); map<string,int>mp; mp.clear(); for(i=1; i<=n; i++) { scanf("%s",a); if(!mp[a])mp[a]=s++; re[i]=mp[a]; Map[mp[a]][mp[a] ]=true; } scanf("%d",&m); for(i=1; i<=m; i++) { scanf("%s%s",a,b); if(!mp[b]) mp[b]=s++; gs[i]=mp[b]; Map[mp[b]][mp[b] ]=true; } scanf("%d",&k); for(i=0; i<k; i++) { scanf("%s%s",a,b); if(!mp[a]) mp[a]=s++; if(!mp[b]) mp[b]=s++; Map[mp[a]][mp[b] ]=true; } Floyd(); memset(cro,-1,sizeof(cro)); int ans=0; for(i=1; i<=m; i++) { memset(use,false,sizeof(use)); ans+=DFS(i); } printf("%d\n",m-ans); } return 0; }