您的位置:首页 > 其它

POJ 1274 / POJ 1469 / POJ 2239 二分图最大匹配

2012-08-05 17:46 381 查看
都是一些很裸的二分图最大匹配.

纯当复习了.

POJ 1274

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
#define bug(s) cout<<#s<<"="<<s<<" "
inline int Rint() {int x; scanf("%d", &x); return x;}
#define MAXN 500
vector<int> G[MAXN];
int vis[MAXN];
int flag[MAXN]; //0-未盖 / 对应点-已盖
int n, m;
int dfs(int u)
{
for(int i=0; i<(int)G[u].size(); i++)
{
int v = G[u][i];
if(!vis[v]) //未访问
{
vis[v] = 1;
if(!flag[v] || dfs(flag[v])) //!!不是dfs(v) -> dfs(flag[v]) 对应点
{
flag[v] = u;
return 1;
}
}
}
return 0;
}
int hungary()
{
memset(flag, 0, sizeof(flag));
int ans=0;
for(int i=1; i<=n; i++) //集合X中点 1~m
{
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
return ans;
}
void print_ans() //输出匹配M
{
for(int i=n+1; i<=n+n; i++) //flag[v]=u...v=m+1~n
if(flag[i]) //v为盖点,输出对应的匹配边
{
printf("%d->%d\n", flag[i], i);
}
}
int main()
{
while(scanf("%d%d", &n, &m)==2)
{
for(int i=1; i<=n; i++)
{
if(!G[i].empty()) G[i].clear();
}
for(int i=1; i<=n; i++)
{
//bug(i);
int v;
char ch;
int cnt = Rint();
while(cnt--)
{
v = Rint();
//bug(v);
G[i].push_back(v+n);
//if(ch == '\n') break;
}
//cout<<endl;
}
printf("%d\n", hungary());
//print_ans();
}
//read_graph();
//printf("%d\n", hungary());
//print_ans();
}

 POJ 1469
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
#define bug(s) cout<<#s<<"="<<s<<" "

#define MAXN 400
#define MAXM MAXN*MAXN
//int G[MAXN][MAXN]; //{U}->{V}
int fa[MAXM], next[MAXM], u[MAXM], v[MAXM], w[MAXM], idx; //边集数组前向星, 表头后面只能跟边, 因为若跟点无法确定下一个点信息
int flag[MAXN]; //盖, flag[{V}] = {U}
int vis[MAXN]; //dfs访问标记, 只对V
int n, m;

void addedge(int tu, int tv, int tw)
{
u[idx] = tu; v[idx] = tv; w[idx] = tw; next[idx] = fa[tu]; fa[tu] = idx++;
}

int dfs(int tu)
{
//vis[u] = 1;

for(int e = fa[tu]; e!=-1; e = next[e])
{
int tv = v[e];
if(vis[tv]) continue;
vis[tv] = 1;
if(!flag[tv] || dfs(flag[tv]))
{
//bug(v);bug(u)<<endl;
flag[tv] = tu;
return 1;
}
}
return 0;
}

int hungry()
{
int ans = 0;
memset(flag, 0, sizeof(flag)); //清空盖点
FOR(i, 1, n) //每次从U出发, 找未盖的V点 or 增广路
{
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
return ans;
}
int main()
{
int T = Rint();
while(T--)
{
scanf("%d%d", &n, &m); // n门课, m个学生
idx = 0;
memset(fa, -1, sizeof(fa));
//memset(G, 0, sizeof(G));
FOR(i, 1, n)
{
int cnt = Rint();
while(cnt--)
{
int tv = Rint();
//G[i][v] = 1;
addedge(i, tv, 1);
}
}
printf("%s\n", hungry() == n? "YES": "NO");
}
}

POJ 2239
这题只要把(星期, 班级)对, hash一下.就行

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
#define bug(s) cout<<#s<<"="<<s<<" "

#define MAXN 1000
#define MAXM MAXN*MAXN
//int G[MAXN][MAXN]; //{U}->{V}
int fa[MAXM], next[MAXM], u[MAXM], v[MAXM], w[MAXM], idx; //边集数组前向星, 表头后面只能跟边, 因为若跟点无法确定下一个点信息
int flag[MAXN]; //盖, flag[{V}] = {U}
int vis[MAXN]; //dfs访问标记, 只对V
int n, m;

void addedge(int tu, int tv, int tw)
{
u[idx] = tu; v[idx] = tv; w[idx] = tw; next[idx] = fa[tu]; fa[tu] = idx++;
}

int dfs(int tu)
{
//vis[u] = 1;

for(int e = fa[tu]; e!=-1; e = next[e])
{
int tv = v[e];
if(vis[tv]) continue;
vis[tv] = 1;
if(!flag[tv] || dfs(flag[tv]))
{
//bug(v);bug(u)<<endl;
flag[tv] = tu;
return 1;
}
}
return 0;
}

int hungry()
{
int ans = 0;
memset(flag, 0, sizeof(flag)); //清空盖点
FOR(i, 1, n) //每次从U出发, 找未盖的V点 or 增广路
{
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
return ans;
}
int main()
{
//int T = Rint();
while(scanf("%d", &n) == 1) // n门课, m天
{
idx = 0;
memset(fa, -1, sizeof(fa));
//memset(G, 0, sizeof(G));
FOR(i, 1, n)
{
int cnt = Rint();
while(cnt--)
{
int tv = Rint();
int cs = Rint();
//G[i][v] = 1;
//addedge(i, (tv-1)*7+cs, 1);
addedge(i, (tv-1)*12+cs, 1); // 把(天, 班级) 哈希即可.
}
}
printf("%d\n", hungry());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  graph