题目链接:点击打开链接
思路:因为每一个左边的匹配点都有一个优先级, 所以我们按照左边的点的优先级排序, 这样就会优先匹配前面的点。 原因很简单 , 我们只要知道匈牙利算法是怎么进行的就可以了: 我们依次枚举每一个左边的点, 对于一个左边点x, 找到一个右边点y, 如果y没有被匹配, 那么(x, y)就是一对新匹配, 如果y已经匹配了x`, 那么我们尝试为x`重新找一个匹配点, 如果找到了那么(x,y)同样是一对新增的匹配。 所以,对于左边的一个x,如果它之前已经被匹配, 那么无论后面如何, 它还是被匹配的。 所以此题就没有什么可说的了。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const double eps = 1e-6; const double PI = acos(-1); const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 500; int T,n,m,use[maxn], from[maxn], tot = 0; struct node { int id, v; bool operator < (const node& rhs) const { return v > rhs.v; } }a[maxn]; vector<int> g[maxn]; bool match(int x) { int len = g[x].size(); for(int i = 0; i < len; i++) if(!use[g[x][i]]) { use[g[x][i]] = true; if(from[g[x][i]] == -1 || match(from[g[x][i]])) { from[g[x][i]] = x; return true; } } return false; } int hungary(int n) { tot = 0; memset(from, -1, sizeof(from)); for(int i = 1; i <= n; i++) { memset(use, 0, sizeof(use)); if(match(a[i].id)) ++tot; } return tot; } int ans[maxn]; int k, v; int main() { while(~scanf("%d",&n)) { for(int i = 1; i <= n; i++) { scanf("%d",&a[i].v); ans[i] = 0; a[i].id = i; } for(int i = 1; i <= n; i++) { scanf("%d",&k); g[i].clear(); for(int j = 1; j <= k; j++) { scanf("%d",&v); g[i].push_back(v); } } sort(a+1, a+n+1); int cur = hungary(n); for(int i = 1; i <= n; i++) { if(from[i] == -1) ; else { ans[from[i]] = i; } } for(int i = 1; i <= n; i++) { printf("%d%c", ans[i], i == n ? '\n' : ' '); } } return 0; }
时间: 2024-10-08 03:49:17