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

来源:互联网 发布:双系统linux安装教程 编辑:程序博客网 时间:2024/04/30 19:06

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


0 0
原创粉丝点击