zoukankan      html  css  js  c++  java
  • HDU 2818 One fihgt one

    HDU_2813

        为了避免读入数据时判重的超时,可以采用哈希去处理,然后再把不重复的人名取出来看做一个点,构图后再用KM算法求二分图最优匹配即可。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define MAXD 210
    #define MAXM 40010
    #define INF 1000000000
    #define HASH 10007
    int headL[HASH], nextL[MAXM], headC[HASH], nextC[MAXM];
    int N, M, K, G[MAXD][MAXD], yM[MAXD], MAX;
    int A[MAXD], B[MAXD], slack[MAXD];
    int visx[MAXD], visy[MAXD];
    char L[MAXD][30], C[MAXD][30], KL[MAXM][30], KC[MAXM][30];
    int w[MAXM], Lr[MAXD], Cr[MAXD];
    int hash(char *str)
    {
    int seed = 131, v = 0;
    while(*str)
    v = v * seed + *(str ++);
    return (v & 0x7FFFFFFF) % HASH;
    }
    int cmp1(const void *_p, const void *_q)
    {
    int *p = (int *)_p;
    int *q = (int *)_q;
    return strcmp(L[*p], L[*q]);
    }
    int cmp2(const void *_p, const void *_q)
    {
    int *p = (int *)_p;
    int *q = (int *)_q;
    return strcmp(C[*p], C[*q]);
    }
    void insert_L(int s)
    {
    int i, h;
    h = hash(KL[s]);
    for(i = headL[h]; i != -1; i = nextL[i])
    if(strcmp(KL[i], KL[s]) == 0)
    break;
    if(i == -1)
    {
    nextL[s] = headL[h];
    headL[h] = s;
    }
    }
    void insert_C(int s)
    {
    int i, h;
    h = hash(KC[s]);
    for(i = headC[h]; i != -1; i = nextC[i])
    if(strcmp(KC[i], KC[s]) == 0)
    break;
    if(i == -1)
    {
    nextC[s] = headC[h];
    headC[h] = s;
    }
    }
    int search_L(char *str)
    {
    int mid, left, right, k;
    left = 0;
    right = N;
    for(;;)
    {
    mid = (left + right) / 2;
    k = strcmp(str, L[Lr[mid]]);
    if(k == 0)
    break;
    else if(k > 0)
    left = mid;
    else
    right = mid;
    }
    return mid;
    }
    int search_C(char *str)
    {
    int mid, left, right, k;
    left = 0;
    right = M;
    for(;;)
    {
    mid = (left + right) / 2;
    k = strcmp(str, C[Cr[mid]]);
    if(k == 0)
    break;
    else if(k > 0)
    left = mid;
    else
    right = mid;
    }
    return mid;
    }
    void init()
    {
    int i, j, k, u, v, nL, nC;
    MAX = 0;
    memset(headL, -1, sizeof(headL));
    memset(headC, -1, sizeof(headC));
    for(i = 0; i < K; i ++)
    {
    scanf("%s%s%d", KL[i], KC[i], &w[i]);
    if(w[i] > MAX)
    MAX = w[i];
    insert_L(i);
    insert_C(i);
    }
    MAX += 100;
    nL = nC = 0;
    for(i = 0; i < HASH; i ++)
    {
    if(headL[i] != -1)
    {
    for(j = headL[i]; j != -1; j = nextL[j])
    strcpy(L[nL ++], KL[j]);
    }
    if(headC[i] != -1)
    {
    for(j = headC[i]; j != -1; j = nextC[j])
    strcpy(C[nC ++], KC[j]);
    }
    }
    for(i = 0; i < N; i ++)
    Lr[i] = i;
    for(i = 0; i < M; i ++)
    Cr[i] = i;
    qsort(Lr, N, sizeof(Lr[0]), cmp1);
    qsort(Cr, M, sizeof(Cr[0]), cmp2);
    memset(G, 0, sizeof(G));
    for(i = 0; i < K; i ++)
    {
    u = search_L(KL[i]);
    v = search_C(KC[i]);
    if(MAX - w[i] > G[u][v])
    G[u][v] = MAX - w[i];
    }
    }
    int searchpath(int u)
    {
    int v, temp;
    visx[u] = 1;
    for(v = 0; v < M; v ++)
    if(!visy[v])
    {
    temp = A[u] + B[v] - G[u][v];
    if(temp == 0)
    {
    visy[v] = 1;
    if(yM[v] == -1 || searchpath(yM[v]))
    {
    yM[v] = u;
    return 1;
    }
    }
    else if(temp < slack[v])
    slack[v] = temp;
    }
    return 0;
    }
    void KM()
    {
    int i, j, temp, u;
    for(i = 0; i < N; i ++)
    {
    A[i] = 0;
    for(j = 0; j < M; j ++)
    if(G[i][j] > A[i])
    A[i] = G[i][j];
    }
    memset(B, 0, sizeof(B));
    memset(yM, -1, sizeof(yM));
    for(u = 0; u < N; u ++)
    {
    for(i = 0; i < M; i ++)
    slack[i] = INF;
    for(;;)
    {
    memset(visx, 0, sizeof(visx));
    memset(visy, 0, sizeof(visy));
    if(searchpath(u))
    break;
    int d = INF;
    for(i = 0; i < M; i ++)
    if(slack[i] < d)
    d = slack[i];
    for(i = 0; i < N; i ++)
    if(visx[i])
    A[i] -= d;
    for(i = 0; i < M; i ++)
    if(visy[i])
    B[i] += d;
    }
    }
    }
    void printresult()
    {
    int i, res = 0;
    for(i = 0; i < M; i ++)
    if(yM[i] != -1)
    res += MAX - G[yM[i]][i];
    printf("%d\n", res);
    }
    int main()
    {
    while(scanf("%d%d%d", &N, &M, &K) == 3)
    {
    init();
    KM();
    printresult();
    }
    return 0;
    }


  • 相关阅读:
    四则运算WEB版
    最大子数组问题
    四则运算终极版
    软件工程个人作业02
    软件工程概论-构建之法阅读笔记01
    软件工程概论个人作业01
    软件工程概论作业-测试
    123
    【好文转载】凡人修真传-程序员的十个等级
    有趣的网站
  • 原文地址:https://www.cnblogs.com/staginner/p/2199721.html
Copyright © 2011-2022 走看看