NYOJ 239 月老的难题
2013-04-17 08:44
218 查看
月老的难题
时间限制:1000 ms | 内存限制:65535 KB难度:4
描述
月老准备给n个女孩与n个男孩牵红线,成就一对对美好的姻缘。
现在,由于一些原因,部分男孩与女孩可能结成幸福的一家,部分可能不会结成幸福的家庭。
现在已知哪些男孩与哪些女孩如果结婚的话,可以结成幸福的家庭,月老准备促成尽可能多的幸福家庭,请你帮他找出最多可能促成的幸福家庭数量吧。
假设男孩们分别编号为1~n,女孩们也分别编号为1~n。
输入第一行是一个整数T,表示测试数据的组数(1<=T<=400)
每组测试数据的第一行有两个整数n,K,其中男孩的人数与女孩的人数都是n。(n<=500,K<=10 000)
随后的K行,每行有两个整数i,j表示第i个男孩与第j个女孩有可能结成幸福的家庭。(1<=i,j<=n)
输出对每组测试数据,输出最多可能促成的幸福家庭数量
样例输入
1 3 4 1 1 1 3 2 2 3 2
样例输出
2
经典的匈牙利算法
算法不解释,主要讲一下优化
首先列出最经典的 易懂的代码
01.
#include <algorithm>
02.
#include <iostream>
03.
#include <cstring>
04.
#include <cstdlib>
05.
#include <string>
06.
#include <vector>
07.
#include <cstdio>
08.
#include <cmath>
09.
//#include <map>
10.
#define FLAG 0
11.
using
namespace
std;
12.
int
map[502][502];
13.
int
num,n;
14.
15.
int
vis[501];
16.
int
lin[501];
17.
inline
int
getnum(
int
i)
18.
{
19.
for
(
int
j=1;j<=n;j++)
20.
{
21.
if
(map[i][j]&&vis[j]==0)
22.
{
23.
vis[j]=1;
24.
if
(lin[j]==0||getnum(lin[j]))
25.
{
26.
lin[j]=i;
27.
return
1;
28.
}
29.
vis[j]=0;
30.
}
31.
}
32.
return
0;
33.
}
34.
int
main()
35.
{
36.
#if(FLAG)
37.
freopen
(
"in.txt"
,
"r"
, stdin);
38.
//freopen("out.txt",
"w",stdout);
39.
#endif
40.
int
k,i,j,T,x,y;
41.
cin>>T;
42.
while
(T--)
43.
{
44.
num=0;
45.
memset
(lin,0,
sizeof
(lin));
46.
//cin>>n>>k;
47.
scanf
(
"%d%d"
,&n,&k);
48.
for
(i=1;i<=k;i++)
49.
{
50.
//cin>>x>>y;
51.
scanf
(
"%d%d"
,&x,&y);
52.
map[x][y]=1;
53.
}
54.
for
(i=1;i<=n;i++)
55.
{
56.
memset
(vis,0,
sizeof
(vis));
57.
if
(getnum(i))
58.
num++;
59.
}
60.
cout<<num<<endl;
61.
}
62.
66.
return
0;
67.
}
很可惜 超时了,需要各种优化,,,
01.
#include <algorithm>
02.
#include <iostream>
03.
#include <cstring>
04.
#include <cstdlib>
05.
#include <string>
06.
#include <queue>
07.
#include <vector>
08.
#include <cstdio>
09.
#include <cmath>
10.
//#include <map>
11.
#define FLAG 0
12.
using
namespace
std;
13.
vector <
int
> map[502];
//用邻接表存储代替邻接矩阵,时间可缩短25倍:解释:500X500矩阵,也就是250000,
14.
//而最多有10000组有效数据(可能结成姻缘的连线)如果用邻接矩阵每次都要搜索250000次
15.
// 邻接表每次只搜索有用数据,就是100000组,所以时间大大缩短
16.
int
num,n;
17.
18.
bool
vis[501];
19.
int
lin[501];
20.
char
c;
21.
inline
int
readin()
//scanf的优化
22.
{
23.
c=
getchar
();
24.
while
(c<
'0'
||c>
'9'
)c=
getchar
();
25.
int
data=0;
26.
do
{
27.
data=data*10+c-
'0'
;c=
getchar
();
28.
}
while
(c<=
'9'
&&c>=
'0'
);
29.
return
data;
30.
}
31.
inline
int
getnum(
int
i)
32.
{
33.
for
(
int
j=0;j<map[i].size();j++)
34.
{
35.
if
(vis[map[i][j]]==0)
36.
{
37.
vis[map[i][j]]=1;
38.
if
(lin[map[i][j]]==0||getnum(lin[map[i][j]]))
39.
{
40.
lin[map[i][j]]=i;
41.
return
1;
42.
}
43.
// vis[map[i][j]]=0;//若果加上这一句的话,NYOJ就会超时,按理说应该是省时间的,和理论不符,不懂,各种郁闷。。。
44.
}
45.
}
46.
return
0;
47.
}
48.
int
main()
49.
{
50.
#if(FLAG)
51.
freopen
(
"out111.txt"
,
"r"
, stdin);
52.
freopen
(
"out.txt"
,
"w"
, stdout);
53.
#endif
54.
int
k,i,j,T,x,y;
55.
cin>>T;
56.
while
(T--)
57.
{
58.
num=0;
59.
int
i=n+1;
60.
while
(i--)
61.
// if(!map[i].empty())
62.
map[i].clear();
63.
memset
(lin,0,
sizeof
(lin));
64.
//cin>>n>>k;
65.
//scanf("%d%d",&n,&k);
66.
n=readin();
67.
k=readin();
68.
for
(i=1;i<=k;i++)
69.
{
70.
//cin>>x>>y;
71.
// scanf("%d%d",&x,&y);
72.
x=readin();
73.
y=readin();
74.
map[x].push_back(y);
75.
}
76.
for
(i=1;i<=n;i++)
77.
{
78.
memset
(vis,0,
sizeof
(vis));
79.
if
(getnum(i))
80.
num++;
81.
}
82.
// cout<<num<<endl;
83.
printf
(
"%d\n"
,num);
84.
}
85.
86.
return
0;
87.
}
下面是牛人的代码,时间超短
01.
#include<iostream>
02.
#include<cstdio>
03.
#include<cstring>
04.
#include<algorithm>
05.
using
namespace
std;
06.
#define CLR(arr,val) memset(arr,val,sizeof(arr))
07.
inline
int
ReadInt()
08.
{
09.
char
ch =
getchar
();
10.
int
data = 0;
11.
while
(ch <
'0'
|| ch >
'9'
) ch =
getchar
();
12.
do
{data = data*10 + ch-
'0'
;ch =
getchar
();}
while
(ch >=
'0'
&& ch <=
'9'
);
13.
return
data;
14.
}
15.
const
int
MAX=510,MAX2=10010;
16.
int
Head[MAX];
17.
int
Next[MAX2];
18.
int
Num[MAX2],top=0;
19.
void
add(
int
u,
int
v)
20.
{
21.
Next[top]=Head[u];
22.
Num[top]=v;
23.
Head[u]=top++;
24.
}
25.
bool
used[MAX];
26.
int
linked[MAX];
27.
bool
Augument(
int
u)
28.
{
29.
for
(
int
i=Head[u];i!=-1;i=Next[i])
30.
{
31.
if
(!used[Num[i]])
32.
{
33.
used[Num[i]]=
true
;
34.
if
(linked[Num[i]]==-1 || Augument(linked[Num[i]]))
35.
{
36.
linked[Num[i]]=u;
37.
return
true
;
38.
}
39.
}
40.
}
41.
return
false
;
42.
}
43.
int
main()
44.
{
45.
for
(
int
m=ReadInt();m--;)
46.
{
47.
int
n=ReadInt();
48.
CLR(Head,-1);
49.
CLR(linked,-1);
50.
top=0;
51.
for
(
int
i=ReadInt();i--;)
52.
add(ReadInt()-1,ReadInt()-1);
53.
int
cnt=0;
54.
for
(
int
i=0;i!=n;i++) { CLR(used,0);
if
(Augument(i))++cnt;}
55.
printf
(
"%d\n"
,cnt);
56.
}
57.
}
相关文章推荐
- NYOJ 237 NYOJ 239 二分图 最大匹配模板题 游戏高手的烦恼 月老的难题 两个题一样
- nyoj 239 月老的难题 (最大二分图匹配匈牙利算法)
- nyoj 239 月老的难题 【二分匹配之匈牙利】
- nyoj 239 月老的难题<二分图匹配>
- NYOJ239月老的难题
- nyoj239月老的难题
- NYOJ 题目239 月老的难题 (二分图最大匹配-匈牙利算法模板)
- nyoj-239 月老的难题 (二分图匹配—匈牙利算法 && 网络流—Dinic算法)
- nyoj239 月老的难题 (匈牙利算法,最大匹配,邻接表)
- 存模版 nyoj 239 月老的难题
- nyoj 239 月老的难题(匈牙利算法+邻接表)
- NYOJ 239 月老的难题(二分图匹配)
- nyoj 239 月老的难题【匈牙利算法+邻接表】
- NYOJ - 239 - 月老的难题 ( 二分图最大匹配 匈牙利算法 )
- NYOJ239月老的难题(二分图的最大匹配模版)
- NYOJ 239-月老的难题
- NYOJ 239 月老的难题(二分图最大匹配)
- NYOJ 239 月老的难题(最大二分图匹配)
- nyoj239 月老的难题 二分图 匈牙利算法
- NYOJ 239-月老的难题