HDU 2853 Assignment & HDU 3315 My Brute

来源:互联网 发布:淘宝网中华活胰宝 编辑:程序博客网 时间:2024/05/16 06:04

两道的题型都是:给出现有的匹配,让你求匹配的权值最大时,改动的边数。

方法就是把边上标记,上标记的方法就是把权值扩大比N大的一个倍数,比如说N:50,那么我们就扩大55倍,原来已经存在的匹配边权值再加1,就这样,无论有原有匹的匹配边有多少条,一定要小于55,通过这样又标记出了没有改变的匹配边。求得ans/55时,这个值就是最大的匹配权值,ans%55就是没有改变的匹配边。

/*HDU 2853*/#include <iostream>#include <cstdlib>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <algorithm>#include <map>#include <cctype>using namespace std;const int maxn = 60;const int INF = 0x3f3f3f3f;int n, m;int W[maxn][maxn];int Lx[maxn], Ly[maxn];int Left[maxn];bool S[maxn], T[maxn];bool match(int i){    S[i] = 1;    for(int j = 1; j <= m; j++) if(Lx[i]+Ly[j] == W[i][j] && !T[j])    {        T[j] = 1;        if(!Left[j] || match(Left[j]))        {            Left[j] = i;            return 1;        }    }    return 0;}void update(){    int a = INF;    for(int i = 1; i <= n; i++) if(S[i])    for(int j = 1; j <= m; j++) if(!T[j])        a = min(a, Lx[i]+Ly[j]-W[i][j]);            for(int i = 1; i <= n; i++)    {        if(S[i]) Lx[i] -= a;    }    for(int j = 1; j <= m; j++)    {        if(T[j]) Ly[j] += a;    }}void KM(){    memset(Left, 0, sizeof(Left));    memset(Lx, 0, sizeof(Lx));    memset(Ly, 0, sizeof(Ly));        for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)            Lx[i] = max(Lx[i], W[i][j]);    }    for(int i = 1; i <= n; i++)    {        for(;;)        {            for(int j = 1; j <= m; j++) S[j] = T[j] = 0;            if(match(i)) break; else update();        }    }}inline void readint(int &x){    char c;    c = getchar();    while(!isdigit(c)) c = getchar();        x = 0;    while(isdigit(c)) x = x*10+c-'0', c = getchar();}inline void writeint(int x){    if(x > 9) writeint(x/10);    putchar(x%10+'0');}int N, M;int sum;void read_case(){n = N, m = M;for(int i = 1; i <= N; i++)for(int j = 1; j <= M; j++){readint(W[i][j]);W[i][j] *= 100;}sum = 0;for(int i = 1; i <= N; i++){int x; readint(x);sum += W[i][x];W[i][x] += 1;}}void solve(){read_case();KM();int ans = 0;for(int i = 1; i <= m; i++) if(Left[i]) ans += W[Left[i]][i];int ans1 = N-ans%100, ans2 = ans/100 - sum/100;writeint(ans1), putchar(' '), writeint(ans2), puts("");}int main(){while(~scanf("%d%d", &N, &M)){solve();}return 0;}

/*HDU 3315*/#include <iostream>#include <cstdlib>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <algorithm>#include <map>#include <cctype>using namespace std;const int maxn = 100;const int INF = 0x3f3f3f3f;int n, m;int W[maxn][maxn];int Lx[maxn], Ly[maxn];int Left[maxn];bool S[maxn], T[maxn];bool match(int i){    S[i] = 1;    for(int j = 1; j <= m; j++) if(Lx[i]+Ly[j] == W[i][j] && !T[j])    {        T[j] = 1;        if(!Left[j] || match(Left[j]))        {            Left[j] = i;            return 1;        }    }    return 0;}void update(){    int a = INF;    for(int i = 1; i <= n; i++) if(S[i])    for(int j = 1; j <= m; j++) if(!T[j])        a = min(a, Lx[i]+Ly[j]-W[i][j]);            for(int i = 1; i <= n; i++)    {        if(S[i]) Lx[i] -= a;    }    for(int j = 1; j <= m; j++)    {        if(T[j]) Ly[j] += a;    }}void KM(){    memset(Left, 0, sizeof(Left));    memset(Lx, 0, sizeof(Lx));    memset(Ly, 0, sizeof(Ly));        for(int i = 1; i <= n; i++)    {        for(int j = 1; j <= m; j++)            Lx[i] = max(Lx[i], W[i][j]);    }    for(int i = 1; i <= n; i++)    {        for(;;)        {            for(int j = 1; j <= m; j++) S[j] = T[j] = 0;            if(match(i)) break; else update();        }    }}inline void readint(int &x){    char c;    c = getchar();    while(!isdigit(c)) c = getchar();        x = 0;    while(isdigit(c)) x = x*10+c-'0', c = getchar();}inline void writeint(int x){    if(x > 9) writeint(x/10);    putchar(x%10+'0');}int N;int V[maxn];int H[maxn], P[maxn];int A[maxn], B[maxn];int check(int i, int j){int Hi = H[i], Pi = P[j];int d1 = A[i], d2 = B[j];for(;;){Pi -= d1;if(Pi <= 0) return 1;Hi -= d2;if(Hi <= 0) return 0;}return -1;}void read_case(){n = m = N;for(int i = 1; i <= N; i++) readint(V[i]);for(int i = 1; i <= N; i++) readint(H[i]);for(int i = 1; i <= N; i++) readint(P[i]);for(int i = 1; i <= N; i++) readint(A[i]);for(int i = 1; i <= N; i++) readint(B[i]);}void build(){for(int i = 1; i <= N; i++)for(int j = 1; j <= N; j++){if(check(i, j) > 0){W[i][j] = V[i]*100;}else{W[i][j] = -V[i]*100;}if(i == j) W[i][j] += 1;}}void solve(){read_case();build();KM();int ans = 0;for(int i = 1; i <= m; i++) if(Left[i]) ans += W[Left[i]][i];if(ans > 0){int ans1 = ans/100;double ans2 = 1.0*(ans%100)/N * 100;printf("%d %.3lf%%\n", ans1, ans2);}else { printf("Oh, I lose my dear seaco!\n"); return ; }}int main(){while(~scanf("%d", &N) && N){solve();}return 0;}


原创粉丝点击