POJ 1087A Plug for UNIX

/* 解题报告: 1、二部图最大匹配:匈牙利求解 2、建图麻烦:用map,传递闭包方式建立 3、由样例输入可得二部图模型: laptop -> a,b,d phone -> c pager -> a,b,d clock -> a,b,d comb -> a,d */ #include <iostream> #include <string> #include <cstring> #include <map> using namespace std; const int MAX1 = 101; const int MAX2 = 400; map<string, int> pluglist; //为每个plug编号,对应关系放到map里 int g[MAX2][MAX2], pluglink[MAX2][MAX2];//存 图,plug之间的连通性 int visited[MAX2], v[MAX2]; //匈牙利法求二部图的最大匹配用的数组 int nl,nr; //依次存放二部图左右结点的个数 //匈牙利法求二部图最大匹配 int dfs(int l) { for(int r=1; r<=nr; r++) { if(!visited[r] && g[l][r]) //如果如果右部的该结点没有被访问,且图是连通的 { visited[r] = 1; if(-1 == v[r] || dfs(v[r])) //如果r未在前一个匹配中,或在前一个匹配中,但从r相邻的结点有增光路径 { v[r] = l; return 1; } } } return 0; } int main() { int n1, n2, n3; string szTemp1, szTemp2; int nPlug = 1; //plug的数量 int anDev[MAX2]; //每个设备对应的plug的ID号 int nAns = 0; //二部图最匹配的数量 cin>>n1; for(int i=1; i<=n1; i++) { cin>>szTemp1; pluglist[szTemp1] = nPlug++; } cin>>n2; for(int i=1; i<=n2; i++) { cin>>szTemp1>>szTemp2; if(!pluglist[szTemp2]) pluglist[szTemp2] = nPlug++; anDev[i] = pluglist[szTemp2]; } cin>>n3; memset(pluglink, 0, sizeof(pluglink)); for(int i=1; i<=n3; i++) { cin>>szTemp1>>szTemp2; if(!pluglist[szTemp1]) pluglist[szTemp1] = nPlug++; if(!pluglist[szTemp2]) pluglist[szTemp2] = nPlug++; pluglink[pluglist[szTemp1]][pluglist[szTemp2]] = 1; } //传递闭包验证每个结点的可联通性 nPlug--; for(int i=1; i<=nPlug; i++) pluglink[i][i] = 1; //不要忘了这一步 for(int k=1; k<=nPlug; k++) for(int i=1; i<=nPlug; i++) for(int j=1; j<=nPlug; j++) pluglink[i][j] = pluglink[i][j] || (pluglink[i][k] && pluglink[k][j]); //建立二分图 nl = n2; nr = n1; memset(g, 0, sizeof(g)); for(int i=1; i<=nl; i++) { int nDev = anDev[i]; for(int j=1; j<=nr; j++) if(pluglink[nDev][j]) g[i][j] = 1; } //匈牙利法求最大匹配 memset(v, -1, sizeof(v)); for(int i=1; i<=nl; i++) { memset(visited, 0, sizeof(visited)); nAns += dfs(i); } cout<<nl-nAns<<endl; return 0; }

你可能感兴趣的:(unix,String,n2)