HDU-3416: Marriage Match II Network Stream + Dichotomy + Union Check Set

analysis

Two points can run xxx round, and then from the source point to each girl, connect a flow rate ofxxOn the side of x , each boy goes to the meeting point with a flow rate ofxxOn the side of x , the flow rate between the boys and girls that can be paired is1 1Side of 1
If you can judge whether boys and girls can be matched, use the adjacency matrix to express the relationship, and then use the union search to judge the relationship between the two girls.

Code

#include <iostream>
#include <cstring>

using namespace std;

const int N = 2010,M = N * N * 2;
const int INF = 0x3f3f3f3f;
int n,m,S,T,k;
int h[N],ne[M],e[M],f[M],idx;
int q[N], d[N], cur[N];
bool st[N][N];
int p[N];

template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
int gcd(int a,int b){
    
    return (b>0)?gcd(b,a%b):a;}

void add(int x,int y,int z){
    
    
    e[idx] = y,ne[idx] = h[x],f[idx] = z,h[x] = idx++;
    e[idx] = x,ne[idx] = h[y],f[idx] = 0,h[y] = idx++;
}

bool bfs(){
    
    
    int hh = 0, tt = 0;
    memset(d,-1,sizeof d);
    q[0] = S, d[S] = 0, cur[S] = h[S];
    while(hh <= tt){
    
    
        int t = q[hh ++ ];
        for(int i = h[t];~i;i = ne[i]){
    
    
            int j = e[i];
            if(d[j] == -1 && f[i]){
    
    
                d[j] = d[t] + 1;
                cur[j] = h[j];
                if(j == T) return true;
                q[ ++ tt] = j;
            }
        }
    }
    return false;
}

int find(int u,int limit){
    
    
    if(u == T) return limit;
    int flow = 0;
    for(int i = cur[u];~i && flow < limit;i = ne[i]){
    
    
        cur[u] = i;
        int j = e[i];
        if(d[j] == d[u] + 1 && f[i]){
    
    
            int t = find(j,min(f[i],limit - flow));
            if(!t) d[j] = -1;
            f[i] -= t,f[i ^ 1] +=t,flow += t;
        }
    }
    return flow;
}

int dinic(){
    
    
    int res = 0,flow;
    while(bfs()) while(flow = find(S,INF)) res += flow;
    return res;
}
int find(int x){
    
    
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

bool check(int mid){
    
    
    memset(h,-1,sizeof h);
    idx = 0;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
            if(st[i][j])
                add(i,j + n,1);
    for(int i = 1;i <= n;i++) add(S,i,mid);
    for(int i = 1;i <= n;i++) add(i + n,T,mid);
    if(dinic() != mid * n) return false;
    return true;
}

int main(){
    
    
    int ssss;
    read(ssss);
    while(ssss--){
    
    
        memset(st,0,sizeof st);
        read(n),read(m),read(k);
        for(int i = 1;i <= n;i++) p[i] = i;
        S = 0,T = n * 2 + 1;
        while(m--){
    
    
            int x,y;
            read(x),read(y);
            st[x][y] = 1;
        }
        while(k--){
    
    
            int x,y;
            read(x),read(y);
            x = find(x),y = find(y);
            p[x] = y;
        }
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++){
    
    
                if(i == j || find(i) != find(j)) continue;
                for(int t = 1;t <= n;t++)
                    if(st[i][t]) st[j][t] = 1;
            }
        int l = 0,r = INF;
        while(l < r){
    
    
            int mid = (l + r + 1) >> 1;
            if(check(mid)) l = mid;
            else r = mid - 1;
        }
        printf("%d\n",l);
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/tlyzxc/article/details/115264577