小记:记得这题之前肯定有做过一次,不过那时候肯定没怎么用心做,所以现在没啥印象,然后刚好这题放在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;
}
}