现在的位置: 首页 > 综合 > 正文

hdu 2813 One fihgt one(trie树+KM算法)

2017年10月18日 ⁄ 综合 ⁄ 共 2264字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.