poj 1087
二分图匹配+floyd求图中节点是否可达。模型很容易想到。此题我认为用网络流最好解释,如果有device有重复的话。二分图建模比较麻烦。一开始没想到这点,用二分图做的,但是AC了,数据应该没有device重复的情况。然后就是判断一个插头通过适配器能转化成什么其他的插头,刚开始用矩阵乘法来判断这个关系,数据一开到500运行时就运行错误(感觉也不是很大啊,至今还不知道原因),后来在网上发现有用floyd做,想了想,确实可以,而且还简单,就是个DP的过程。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <map> 6 #include <string> 7 using namespace std; 8 const int maxn=500+10; 9 int n,m,k,tot; 10 map<string,int> a1; 11 map<string,int> a2; 12 int bi[maxn][maxn]; 13 int x[maxn],y[maxn],ch[maxn],mark[maxn]; 14 int g[maxn][maxn]; 15 int dfs(int u) 16 { 17 int v; 18 for(v=1;v<=n;v++) 19 { 20 if(bi[u][v]&&!ch[v]) 21 { 22 ch[v]=1; 23 if(!y[v]||dfs(y[v])) 24 { 25 y[v]=u;x[u]=v; 26 return 1; 27 } 28 //ch[v]=0; ch[v]不用置为0,从v没有增广路,以后不管那条只要走到v肯定还没有增广路,所以直接把他标记,省的以后再来搞她 29 } 30 } 31 return 0; 32 } 33 int MaxMatch() 34 { 35 memset(x,0,sizeof(x)); 36 memset(y,0,sizeof(y)); 37 int i,sum=0; 38 for(i=1;i<=m;i++) 39 { 40 memset(ch,0,sizeof(ch)); 41 if(dfs(i)) sum++; 42 } 43 return sum; 44 } 45 void floyd() 46 { 47 int i,j,k; 48 for(k=1;k<=tot;k++) 49 { 50 for(i=1;i<=tot;i++) 51 { 52 for(j=1;j<=tot;j++) 53 g[i][j]=g[i][j]||(g[i][k]&&g[k][j]); 54 } 55 } 56 } 57 int main() 58 { 59 scanf("%d",&n); 60 int i; 61 string s1,s2; 62 tot=0; 63 for(i=0;i<n;i++) 64 { 65 cin>>s1; 66 a1[s1]=++tot; 67 } 68 scanf("%d",&m); 69 int u,v; 70 for(i=1;i<=m;i++) 71 { 72 cin>>s1>>s2; 73 if(!a1[s2]) a1[s2]=++tot; 74 v=a1[s2]; 75 mark[i]=v; 76 } 77 scanf("%d",&k); 78 for(i=0;i<k;i++) 79 { 80 cin>>s1>>s2; 81 if(!a1[s1]) a1[s1]=++tot; if(!a1[s2]) a1[s2]=++tot; 82 u=a1[s1]; v=a1[s2]; 83 g[u][v]=1; 84 } 85 for(i=1;i<=tot;i++) g[i][i]=1; 86 floyd(); 87 for(i=1;i<=m;i++) 88 { 89 u=mark[i]; 90 for(v=1;v<=n;v++) 91 { 92 if(g[u][v]) bi[i][v]=1; 93 } 94 } 95 printf("%d\n",m-MaxMatch()); 96 return 0; 97 }