CSU-1531 Jewelry Exhibition —— 二分图匹配(最小覆盖点)
题目链接:https://vjudge.net/problem/CSU-1531
Input
Output
Sample Input
2 1 5 3 0.2 1.5 0.3 4.8 0.4 3.5 4 4 8 0.7 0.5 1.7 0.5 2.8 1.5 3.7 0.5 2.2 3.6 2.7 2.7 1.2 2.2 1.2 2.7
Sample Output
1 3
题解:
一开始想用DP做,后来发现不行,因为新加入的点会破坏前面的结果,且不知道前面的状态如何,所以不能用动态规划的思想去解题。
1.用最少的边去覆盖掉所有的点,顾名思义,可以用二分图的最小覆盖点去做,只是这题的“点”为二分图的边,这题的"边"为二分图的点。
2.把题目的点的x、y坐标看做二分图的点,把题目的点当做二分图的边,其两端是x、y坐标,这样就转化成了用最少的点去覆盖掉所有的边。
代码一(矩阵):
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 #define eps 0.0000001 17 typedef long long LL; 18 const int INF = 2e9; 19 const LL LNF = 9e18; 20 const int mod = 1e9+7; 21 const int maxn = 100+10; 22 23 int G[maxn][maxn]; 24 int vis[maxn], match[maxn]; 25 int n,m,k; 26 27 int find(int u) 28 { 29 for(int i = 0; i<m; i++) 30 { 31 if(G[u][i] && !vis[i] ) 32 { 33 vis[i] = 1; 34 if(match[i]==-1 || find(match[i])) 35 { 36 match[i] = u; 37 return 1; 38 } 39 } 40 } 41 return 0; 42 } 43 44 void solve() 45 { 46 double x,y; 47 scanf("%d%d%d",&n,&m,&k); 48 49 ms(G,0); 50 for(int i = 0; i<k; i++) 51 { 52 scanf("%lf%lf",&x,&y); 53 G[(int)x][(int)y] = 1; 54 } 55 56 int ans = 0; 57 ms(match,-1); 58 for(int i = 0; i<n; i++) 59 { 60 ms(vis,0); 61 if(find(i)) 62 ans++; 63 } 64 printf("%d\n",ans); 65 } 66 67 int main() 68 { 69 int T; 70 scanf("%d",&T); 71 while(T--){ 72 solve(); 73 } 74 75 return 0; 76 }
代码二(vector):
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 #define pb push_back 14 #define mp make_pair 15 #define ms(a, b) memset((a), (b), sizeof(a)) 16 #define eps 0.0000001 17 typedef long long LL; 18 const int INF = 2e9; 19 const LL LNF = 9e18; 20 const int mod = 1e9+7; 21 const int maxn = 100+10; 22 23 vector<int> G[maxn]; 24 int vis[maxn], match[maxn]; 25 int n,m,k; 26 27 int find(int u) 28 { 29 int Size = G[u].size(); 30 for(int i = 0; i<Size; i++) 31 { 32 int v = G[u][i]; 33 if(!vis[v] ) 34 { 35 vis[v] = 1; 36 if(match[v]==-1 || find(match[v])) 37 { 38 match[v] = u; 39 return 1; 40 } 41 } 42 } 43 return 0; 44 } 45 46 void solve() 47 { 48 double x,y; 49 scanf("%d%d%d",&n,&m,&k); 50 51 for(int i = 0; i<n; i++) 52 G[i].clear(); 53 for(int i = 0; i<k; i++) 54 { 55 scanf("%lf%lf",&x,&y); 56 G[(int)x].pb((int)y); 57 } 58 59 int ans = 0; 60 ms(match,-1); 61 for(int i = 0; i<n; i++) 62 { 63 ms(vis,0); 64 if(find(i)) 65 ans++; 66 } 67 printf("%d\n",ans); 68 } 69 70 int main() 71 { 72 int T; 73 scanf("%d",&T); 74 while(T--){ 75 solve(); 76 } 77 78 return 0; 79 }