hdu 3718
一个二分图最大匹配的题;
匈牙利算法不熟;
建了个模,用最小费用最大流解决了
1 #include <iostream> 2 #include <cstring> 3 #define INF 9999999 4 #include <cstdio> 5 #include <queue> 6 #include <vector> 7 #include<algorithm> 8 using namespace std; 9 #define maxn 6100 10 11 struct edge 12 { 13 int from,to,cap,flow,cost; 14 }; 15 struct MCMF 16 { 17 int n,m,s,t; 18 vector<edge>edges; 19 vector<int>G[maxn]; 20 int inq[maxn]; 21 int d[maxn]; 22 int p[maxn]; 23 int a[maxn]; 24 void init(int n) 25 { 26 this->n=n; 27 for(int i=0; i<n; i++) 28 G[i].clear(); 29 edges.clear(); 30 } 31 void addedge(int from,int to,int cap,int cost) 32 { 33 edges.push_back((edge){from,to,cap,0,cost}); 34 edges.push_back((edge){to,from,0,0,-cost}); 35 m=edges.size(); 36 G[from].push_back(m-2); 37 G[to].push_back(m-1); 38 } 39 40 bool bellman(int s,int t,int &flow,int &cost) 41 { 42 for(int i=0; i<n; i++)d[i]=INF; 43 memset(inq,0,sizeof(inq)); 44 d[s]=0; 45 inq[s]=1; 46 p[s]=0; 47 a[s]=INF; 48 49 queue<int>Q; 50 Q.push(s); 51 while(!Q.empty()) 52 { 53 int u = Q.front(); 54 Q.pop(); 55 inq[u] = 0; 56 for(int i = 0; i < G[u].size(); i++) 57 { 58 edge& e = edges[G[u][i]]; 59 if(e.cap > e.flow && d[e.to] > d[u] + e.cost) 60 { 61 d[e.to] = d[u] + e.cost; 62 p[e.to] = G[u][i]; 63 a[e.to] = min(a[u], e.cap - e.flow); 64 if(!inq[e.to]) 65 { 66 Q.push(e.to); 67 inq[e.to] = 1; 68 } 69 } 70 } 71 } 72 if(d[t] == INF) return false; 73 flow += a[t]; 74 cost += d[t]*a[t]; 75 int u = t; 76 while(u != s) 77 { 78 edges[p[u]].flow += a[t]; 79 edges[p[u]^1].flow -= a[t]; 80 u = edges[p[u]].from; 81 } 82 return true; 83 } 84 int Mincost(int s, int t) 85 { 86 int flow = 0, cost = 0; 87 while(bellman(s, t, flow, cost)); 88 return cost; 89 } 90 }; 91 int n; 92 int k,m; 93 char s2[10200],s1[10200]; 94 int cur[30][30]; 95 int tot[30]; 96 void first_solve() 97 { 98 memset(cur,0,sizeof(cur)); 99 memset(tot,0,sizeof(tot)); 100 for(int i=1; i<=n; i++) 101 { 102 int k1=s1[i]-'A'+1; 103 int k2=s2[i]-'A'+1; 104 tot[k1]++; 105 cur[k1][k2]++; 106 } 107 } 108 MCMF solve; 109 int main() 110 { 111 int t; 112 int st=0; 113 int final=201; 114 scanf("%d",&t); 115 while(t--) 116 { 117 scanf("%d%d%d",&n,&k,&m); 118 for(int i=1; i<=n; i++) 119 { 120 char s[5]; 121 scanf("%s",s); 122 s1[i]=s[0]; 123 } 124 for(int d=1; d<=m; d++) 125 { 126 solve.init(final+1); 127 for(int j=1; j<=n; j++) 128 { 129 char s[5]; 130 scanf("%s",s); 131 s2[j]=s[0]; 132 } 133 first_solve(); 134 for(int i=1; i<=26; i++) 135 solve.addedge(st,i,1,0); 136 for(int i=1; i<=26; i++) 137 { 138 for(int j=1; j<=26; j++) 139 { 140 int cnt=26+j; 141 if (cur[i][j]) 142 solve.addedge(i,cnt,1,tot[i]-cur[i][j]); 143 else solve.addedge(i,cnt,1,tot[i]); 144 } 145 } 146 for(int i=1;i<=26;i++)solve.addedge(i+26,final,1,0); 147 int ans=n-solve.Mincost(st,final); 148 printf("%.4lf\n",(double)ans/(double)n); 149 } 150 } 151 return 0; 152 }