二分圖匹配+floyd求圖中節點是否可達。模型很容易想到。此題我認爲用網絡流最好解釋,若是有device有重複的話。二分圖建模比較麻煩。一開始沒想到這點,用二分圖作的,可是AC了,數據應該沒有device重複的狀況。而後就是判斷一個插頭經過適配器能轉化成什麼其餘的插頭,剛開始用矩陣乘法來判斷這個關係,數據一開到500運行時就運行錯誤(感受也不是很大啊,至今還不知道緣由),後來在網上發現有用floyd作,想了想,確實能夠,並且還簡單,就是個DP的過程。ios
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 }