小记:记得这题之前肯定有做过一次,不过那时候肯定没怎么用心做,所以现在没啥印象,然后刚好这题放在trie树的题里,直接用trie树搞了
思路:这题一看就是KM算法的应用,KM算法求边权最大的最佳匹配,这里求得是疲劳值最小的,那么将值反一下即可。最后再反过来就是答案了
但是名字是字符串的,那么必须转化过来,然后用邻接矩阵存下图,再套KM模板即可
这里我转化是用trie树的,因为名字大小写都有,所以每次trie树要保证大小写都能存入树中,
搞定好转化之后,套入kM模板,直接1a
代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> using namespace std; #define mst(a,b) memset(a,b,sizeof(a)) #define eps 10e-8 const int MAX_ = 210; const int MAX = 60; const int N = 500010; const int INF = (1<<30); typedef struct Node{ int isStr; //int num; struct Node *next[MAX]; Node():isStr(-1){ memset(next, NULL, sizeof(next)); } ~Node(){ for(int i = 0;i < MAX; ++i) if(next[i] != NULL) delete next[i]; } }TrieNode,*Trie; Trie root , root1; char s[MAX_], str[MAX_]; int l[MAX_],r[MAX_], ln[MAX_],rn[MAX_]; int link[MAX_], mp[MAX_][MAX_]; int n, m; void Insert(bool flag, char *s, int num){ TrieNode *p; if(flag)p = root; else p = root1; while(*s){ if(p ->next[*s-'A'] == NULL){ p ->next[*s-'A'] = new TrieNode; } p = p ->next[*s-'A']; s++; } p->isStr = num; } int find(bool flag, char *s){ int i = 0; TrieNode *p; if(flag)p=root;else p = root1; while(*s){ if(p->next[*s-'A'] == NULL)return -1; p = p->next[*s-'A']; s++; } return p->isStr; } void init(){ memset(link,-1,sizeof(link)); memset(rn,0,sizeof(rn)); for(int i = 0; i < n; i++){ ln[i] = -INF; for(int j = 0; j < m; j++){ ln[i] = max(ln[i],mp[i][j]); } } } int dfs(int k) { l[k] = 1; for(int i = 0; i < m; i++) { if(!r[i]&&ln[k] + rn[i] == mp[k][i]) { r[i] = 1; if(link[i] == -1 || dfs(link[i])) { link[i] = k; return 1; } } } return 0; } void adjust(){ int minm = INF; for(int i = 0; i < n; i ++){ if(l[i]){ for(int j = 0; j < m; j++){ if(!r[j]){ minm = min(minm,ln[i]+rn[j]-mp[i][j]); } } } } for(int i = 0; i < n; i++){ if(l[i]){ ln[i] -= minm; } } for(int i = 0; i < m; i++){ if(r[i]){ rn[i] += minm; } } } int main() { int ans, cnt1, cnt2, len, T, k, inj, st, et; bool flag; flag = true; //ans = 0;flag = false;cnt = 0; while(scanf("%d%d%d", &n, &m, &k) != EOF){ for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ mp[i][j] = -INF; } } cnt1 = cnt2 = 0; root = new TrieNode; root1 = new TrieNode; while(k -- && scanf("%s%s%d",s,str, &inj)){ st = find(true,s); if(st == -1){ st = cnt1++; Insert(true, s, st); } et = find(false, str); if(et == -1){ et = cnt2++; Insert(false, str, et); } mp[st][et] = -inj; } init(); for(int i = 0; i < n; i++){ while(1){ mst(l,0); mst(r,0); if(dfs(i))break; else adjust(); } } ans = 0; for(int i = 0; i < m; i++){ if(link[i] > -1) ans += mp[link[i]][i]; } printf("%d\n",-ans); delete root; delete root1; } }