hdu - 2063 - 过山车(二分图最大匹配)

题意:有M个女生,N个男生,他们要玩过山车又必须是一男一女一起,女生只愿意和她心中的几位男生坐在一起,问最多能匹配多少对。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063

——>>刚学了一个二分图的匈牙利算法,但那是一个无向图,编号从1到最后,而题中的是女N人,男M人,编号分别从1开始,这就纳闷了,于是试下将男生编号全部加上女生人数得到男生新编号,没料到不但没TLE,还0ms过,壮哉!

#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;

const int maxn = 1000 + 10;
vector<int> G[maxn];
bool vis[maxn];
int fa[maxn];

bool dfs(int u)
{
    int d = G[u].size();
    for(int i = 0; i < d; i++)
    {
        int v = G[u][i];
        if(!vis[v])
        {
            vis[v] = 1;
            int temp = fa[v];
            fa[v] = u;
            if(temp == -1 || dfs(temp)) return 1;
            fa[v] = temp;
        }
    }
    return 0;
}
int main()
{
    int K, M, N, i, u, v;
    while(~scanf("%d", &K))
    {
        if(!K) return 0;
        for(i = 0; i < maxn; i++) G[i].clear();
        scanf("%d%d", &M, &N);
        int n = M + N;
        for(i = 0; i < K; i++)
        {
            scanf("%d%d", &u, &v);
            G[u].push_back(v + M);
            G[v + M].push_back(u);
        }
        memset(fa, -1, sizeof(fa));
        for(i = 1; i <= n; i++)
        {
            memset(vis, 0, sizeof(vis));
            dfs(i);
        }
        int cnt = 0;
        for(i = 1; i <= n; i++) if(fa[i] != -1) cnt++;
        printf("%d\n", cnt/2);
    }
    return 0;
}


也用Java写了个,但运行时间多了好多,171ms:

import java.util.Scanner;

public class Main {

	static final int maxn = 1000 + 10;
	static boolean G[][] = new boolean[maxn][maxn], vis[] = new boolean[maxn];
	static int fa[] = new int[maxn], n;
	public static boolean dfs(int u){
		for(int i = 1; i <= n; i++) if(G[u][i] == true && vis[i] == false){
			vis[i] = true;
			int temp = fa[i];
			fa[i] = u;
			if(temp == -1 || dfs(temp) == true) return true;
			fa[i] = temp;
		}
		return false;
	}
	public static void main(String[] args) {
		int K, M, N, i, j;
		Scanner cin = new Scanner(System.in);
		while(cin.hasNextInt()){
			K = cin.nextInt();
			if(K == 0) break;
			M = cin.nextInt();
			N = cin.nextInt();
			n = M + N;
			for(i = 1; i <= n; i++)
				for(j = 1; j <= n; j++)
					G[i][j] = false;
			for(i = 0; i < K; i++){
				int u = cin.nextInt();
				int v = cin.nextInt();
				G[u][v+M] = true;
				G[v+M][u] = true;
			}
			for(i = 1; i <= n; i++) fa[i] = -1;
			for(i = 1; i <= n; i++){
				for(j = 1; j <= n; j++) vis[j] = false;
				dfs(i);
			}
			int cnt = 0;
			for(i = 1; i <= n; i++) if(fa[i] != -1) cnt++;
			System.out.println(cnt/2);
		}
		cin.close();
	}

}

2014.5.10,再来(1228KB内存,0MS):

#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 500 + 10;

bool S[maxn], T[maxn];
int M, N, w[maxn][maxn], left[maxn];

bool match(int x) {
    S[x] = true;
    for(int i = 1; i <= N; i++) if(w[x][i] && !T[i]) {
        T[i] = true;
        if(!left[i] || match(left[i])) {
            left[i] = x;
            return true;
        }
    }
    return false;
}

int main()
{
    int K, G, B;
    while(scanf("%d", &K) && K) {
        scanf("%d%d", &M, &N);
        memset(w, 0, sizeof(w));
        for(int i = 0; i < K; i++) {
            scanf("%d%d", &G, &B);
            w[G][B] = 1;
        }
        memset(left, 0, sizeof(left));
        for(int i = 1; i <= M; i++) {
            memset(S, 0, sizeof(S));
            memset(T, 0, sizeof(T));
            match(i);
        }
        int cnt = 0;
        for(int i = 1; i <= N; i++)
            if(left[i])
                cnt++;
        printf("%d\n", cnt);
    }
    return 0;
}

再来(224KB内存,0MS):

#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 500 + 10;

bool S[maxn], T[maxn];
int M, N, left[maxn];
int hed[maxn<<1], nxt[maxn<<1], v[maxn<<1], ecnt;

void init() {
    memset(hed, -1, sizeof(hed));
    ecnt = 0;
}

void add_edge(int uu, int vv) {
    v[ecnt] = vv;
    nxt[ecnt] = hed[uu];
    hed[uu] = ecnt++;
}

bool match(int x) {
    S[x] = true;
    for(int e = hed[x]; e != -1; e = nxt[e]) {
        int to = v[e];
        if(!T[to]) {
            T[to] = true;
            if(!left[to] || match(left[to])) {
                left[to] = x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    int K, G, B;
    while(scanf("%d", &K) && K) {
        scanf("%d%d", &M, &N);
        init();
        for(int i = 0; i < K; i++) {
            scanf("%d%d", &G, &B);
            add_edge(G, B);
        }
        memset(left, 0, sizeof(left));
        for(int i = 1; i <= M; i++) {
            memset(S, 0, sizeof(S));
            memset(T, 0, sizeof(T));
            match(i);
        }
        int cnt = 0;
        for(int i = 1; i <= N; i++)
            if(left[i])
                cnt++;
        printf("%d\n", cnt);
    }
    return 0;
}


你可能感兴趣的:(hdu - 2063 - 过山车(二分图最大匹配))