hdu3081 Marriage Match II

hdu3081 Marriage Match II

题意:有2*n个人,其中有n个女生,n个男生,其中有m对关系,表示女生a可以和男生b配对,又有f对关系,表示女生c和女生d是朋友,女生c可以配对所有女生d可以配对到的男生。请问最多可以配对多少轮(可以匹配多一轮表示所有女生可以匹配与当前这一轮完全不同的男生)

这道题啊,很显然是网络流啦,然后题目要求最多,那就二分枚举答案咯

至于构图嘛,也是很裸的,因为数据范围是 n100 ,所以可以暴力连女生 i 可以到达的所有男生 j 。然后对于二分枚举的答案 mid ,从源连到每个女生,从每个男生连到汇,流量都为 mid ,然后做一次最大流判断是否满流就可以知道是否满足条件

然后就是傻逼呵呵的代码了..

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int Maxn = 110;
struct node {
    int x, y, next, c, opp;
}a[Maxn*Maxn*10]; int first[Maxn*2], len;
int _min ( int x, int y ){ return x < y ? x : y; }
void ins ( int x, int y, int c ){
    len ++; int k1 = len;
    a[len].x = x; a[len].y = y; a[len].c = c;
    a[len].next = first[x]; first[x] = len;
    len ++; int k2 = len;
    a[len].x = y; a[len].y = x; a[len].c = 0;
    a[len].next = first[y]; first[y] = len;
    a[k1].opp = k2;
    a[k2].opp = k1;
}
int n, m, K;
int st, ed, h[Maxn*2];
bool v[Maxn][Maxn];
int fa[Maxn];
int ff ( int x ){
    if ( fa[x] == x ) return x;
    return fa[x] = ff (fa[x]);
}
bool bfs (){
    queue <int> q;
    memset ( h, -1, sizeof (h) ); h[st] = 0;
    q.push (st);
    while ( !q.empty () ){
        int x = q.front (); q.pop ();
        for ( int k = first[x]; k; k = a[k].next ){
            int y = a[k].y;
            if ( h[y] == -1 && a[k].c > 0 ){
                h[y] = h[x]+1;
                q.push (y);
            }
        }
    }
    return h[ed] > 0;
}
int dfs ( int x, int flow ){
    if ( x == ed ) return flow;
    int delta = 0;
    for ( int k = first[x]; k; k = a[k].next ){
        int y = a[k].y;
        if ( h[y] == h[x]+1 && a[k].c > 0 && flow-delta > 0 ){
            int minf = dfs ( y, _min ( a[k].c, flow-delta ) );
            delta += minf;
            a[k].c -= minf;
            a[a[k].opp].c += minf;
        }
    }
    if ( delta == 0 ) h[x] = -1;
    return delta;
}
int main (){
    int i, j, k, T;
    scanf ( "%d", &T );
    while ( T -- ){
        scanf ( "%d%d%d", &n, &m, &K );
        memset ( v, false, sizeof (v) );
        for ( i = 1; i <= m; i ++ ){
            int x, y;
            scanf ( "%d%d", &x, &y );
            v[x][y] = true;
        }
        for ( i = 1; i <= n; i ++ ) fa[i] = i;
        for ( i = 1; i <= K; i ++ ){
            int x, y;
            scanf ( "%d%d", &x, &y );
            int fx = ff (fa[x]), fy = ff (fa[y]);
            if ( fx != fy ){
                fa[fx] = fy;
            }
        }
        for ( i = 1; i <= n; i ++ ){
            int fi = ff (fa[i]);
            for ( j = 1; j <= n; j ++ ){
                int fj = ff (fa[j]);
                if ( fi == fj ){
                    for ( k = 1; k <= n; k ++ ){
                        v[i][k] |= v[j][k];
                    }
                }
            }
        }
        int l = 0, r = n, ret;
        while ( l <= r ){
            int mid = ( l + r ) >> 1;
            len = 0; memset ( first, 0, sizeof (first) );
            st = 0; ed = 2*n+1;
            for ( i = 1; i <= n; i ++ ){
                ins ( st, i, mid );
                ins ( i+n, ed, mid );
            }
            for ( i = 1; i <= n; i ++ ){
                for ( j = 1; j <= n; j ++ ){
                    if ( v[i][j] == true ) ins ( i, j+n, 1 );
                }
            }
            int ans = 0, delta;
            while ( bfs () ){
                while ( delta = dfs ( st, 0x7fffffff ) ) ans += delta;
            }
            if ( ans == n*mid ){ ret = mid; l = mid+1; }
            else r = mid-1;
        }
        printf ( "%d\n", ret ); 
    }
    return 0;
}

也WA了几次,总结一下错误的原因吧
1.傻逼呵呵看错题
2.明明有2*n个人,只开n个点..
真的是傻逼..

你可能感兴趣的:(hdu3081 Marriage Match II)