题目大意:
有电器和配套的插座,以及每种无限个的装换插头
问:最少多少电器用不上电?
画画图,可以知道是一个二分图,中间结点需要用传递闭包优化掉
Floyd+匈牙利算法(二分图匹配)
1 #include<map> 2 #include<cmath> 3 #include<queue> 4 #include<cstdio> 5 #include<cstring> 6 #include<iostream> 7 using namespace std; 8 const int N=800+10; 9 string plug,device,plug0,plug1; 10 int n,m,k,g[N][N],match[N],used[N]; 11 void floyd(int sz) { //传递闭包 12 for(int k=1; k<=sz; k++) 13 for(int i=1; i<=sz; i++) 14 for(int j=1; j<=sz; j++) 15 g[i][j]|=(g[i][k]&&g[k][j]); 16 } 17 bool dfs(int u) { 18 for(int i=1; i<=m; i++) 19 if(!used[i]&&g[u][i]) { 20 used[i]=1; 21 if(match[i]==-1||dfs(match[i])) { 22 match[i]=u; 23 return true; 24 } 25 } 26 return false; 27 } 28 int hungary() { 29 int res=0; 30 memset(match,-1,sizeof(match)); 31 for(int i=m+n+101; i<=m+n+101+n; res+=dfs(i++)) 32 memset(used,0,sizeof(used)); 33 return n-res; 34 } 35 int main() { 36 while(~scanf("%d",&m)) { 37 memset(g,0,sizeof(g)); 38 map<string,int>q0,q1;//q0 for plugs and q1 for devices 39 for(int i=1; i<=m; i++)cin>>plug,q0[plug]=i; 40 scanf("%d",&n); 41 int tmpn=m+n+100,tmpm=m;//100 is the max value of k 42 for(int i=1; i<=n; i++) { 43 cin>>device>>plug; 44 q1[device]=++tmpn; 45 if(!q0[plug]) q0[plug]=++tmpm; 46 g[q1[device]][q0[plug]]=1; 47 } 48 scanf("%d",&k); 49 for(int i=1; i<=k; i++) { 50 cin>>plug0>>plug1; 51 if(!q0[plug0]) q0[plug0]=++tmpm; 52 if(!q0[plug1]) q0[plug1]=++tmpm; 53 g[q0[plug0]][q0[plug1]]=1;//单向传递 54 } 55 floyd(tmpn); 56 printf("%d ",hungary()); 57 } 58 return 0; 59 }