Hungary算法
.c
#include <std<pre name="code" class="cpp">#include <iostream>
#include <cstring>
using namespace std;
//定義鏈表
struct link {
int data; //存放數據
link* next; //指向下一個節點
link(int=0);
};
link::link(int n) {
data=n;
next=NULL;
}
int n1,n2,m,ans=0;
int result[101]; //記錄n1中的點匹配的點的編號
bool state [101]; //記錄n1中的每個點是否被搜索過
link *head [101]; //記錄n2中的點的鄰接節點
link *last [101]; //鄰接表的終止位置記錄
//判斷能否找到從節點n開始的增廣路
bool find(const int n) {
link* t=head[n];
while (t!=NULL) { //n仍有未查找的鄰接節點時
if (!(state[t->data])) { //如果鄰接點t->data未被查找過
state[t->data]=true; //標記t->data爲已經被找過
if ((result[t->data]==0) || //如果t->data不屬於前一個匹配M
(find(result[t->data]))) { //如果t->data匹配到的節點可以尋找到增廣路
result[t->data]=n; //那麼可以更新匹配M',其中n1中的點t->data匹配n
return true; //返回匹配成功的標誌
}
}
t=t->next; //繼續查找下一個n的鄰接節點
}
return false;
}
int main() {
int t1=0,t2=0;
cin>>n1>>n2>>m;
for (int i=0; i<m; i++) {
cin>>t1>>t2;
if (last[t1]==NULL)
last[t1]=head[t1]=new link(t2);
else
last[t1]=last[t1]->next=new link(t2);
}
for (int i=1; i<=n1; i++) {
memset(state,0,sizeof(state));
if (find(i)) ans++;
}
cout<<ans<<endl;
return 0;
}
io.h>#include <string.h>int n1,n2,m,ans;int result[101]; //記錄V2中的點匹配的點的編號bool state [101]; //記錄V2中的每個點是否被搜索過bool data[101][101];//鄰接矩陣 true代表有邊相連void init() { int t1,t2; memset(data,0,sizeof(data)); memset(result,0,sizeof(result)); ans = 0; scanf("%d%d%d",&n1,&n2,&m); for (int i = 1; i <= m; i++) { scanf("%d%d",&t1,&t2); data[t1][t2] = true; } return;}bool find(int a) { for (int i = 1; i <= n2; i++) { if (data[a][i] == 1 && !state[i]) { //如果節點i與a相鄰並且未被查找過 state[i] = true; //標記i爲已查找過 if (result[i] == 0 //如果i未在前一個匹配M中 || find(result[i])) { //i在匹配M中,但是從與i相鄰的節點出發可以有增廣路 result[i] = a; //記錄查找成功記錄 return true; //返回查找成功 } } } return false;}int main() { init(); for (int i = 1; i <= n1; i++) { memset(state,0,sizeof(state)); //清空上次搜索時的標記 if (find(i)) ans++; //從節點i嘗試擴展 } printf("%d\n",ans); return 0;}
.cpp
#include<iostream>
#include<cstring>
using namespace std;
int map[105][105];
int visit[105],flag[105];
int n,m;
bool dfs(int a) {
for(int i=1;i<=n;i++) {
if(map[a][i] && !visit[i]) {
visit[i]=1;
if(flag[i]==0 || dfs(flag[i])) {
flag[i]=a;
return true;
}
}
}
return false;
}
int main() {
while(cin>>n>>m) {
memset(map,0,sizeof(map));
for(int i=1;i<=m;i++) {
int x,y;
cin>>x>>y;
map[x][y]=1;
}
memset(flag,0,sizeof(flag));
int result=0;
for(int i=1;i<=n;i++) {
memset(visit,0,sizeof(visit));
if(dfs(i)) result++;
}
cout<<result<<endl;
}
return 0;
}
link.cpp
#include <iostream>
#include <cstring>
using namespace std;
//定義鏈表
struct link {
int data; //存放數據
link* next; //指向下一個節點
link(int=0);
};
link::link(int n) {
data=n;
next=NULL;
}
int n1,n2,m,ans=0;
int result[101]; //記錄n1中的點匹配的點的編號
bool state [101]; //記錄n1中的每個點是否被搜索過
link *head [101]; //記錄n2中的點的鄰接節點
link *last [101]; //鄰接表的終止位置記錄
//判斷能否找到從節點n開始的增廣路
bool find(const int n) {
link* t=head[n];
while (t!=NULL) { //n仍有未查找的鄰接節點時
if (!(state[t->data])) { //如果鄰接點t->data未被查找過
state[t->data]=true; //標記t->data爲已經被找過
if ((result[t->data]==0) || //如果t->data不屬於前一個匹配M
(find(result[t->data]))) { //如果t->data匹配到的節點可以尋找到增廣路
result[t->data]=n; //那麼可以更新匹配M',其中n1中的點t->data匹配n
return true; //返回匹配成功的標誌
}
}
t=t->next; //繼續查找下一個n的鄰接節點
}
return false;
}
int main() {
int t1=0,t2=0;
cin>>n1>>n2>>m;
for (int i=0; i<m; i++) {
cin>>t1>>t2;
if (last[t1]==NULL)
last[t1]=head[t1]=new link(t2);
else
last[t1]=last[t1]->next=new link(t2);
}
for (int i=1; i<=n1; i++) {
memset(state,0,sizeof(state));
if (find(i)) ans++;
}
cout<<ans<<endl;
return 0;
}
byvoid
#include <stdio.h>
#include <string.h>
#define MAX 102
long n,n1,match;
long adjl[MAX][MAX];
long mat[MAX];
bool used[MAX];
FILE *fi,*fo;
void readfile()
{
fi=fopen("flyer.in","r");
fo=fopen("flyer.out","w");
fscanf(fi,"%ld%ld",&n,&n1);
long a,b;
while (fscanf(fi,"%ld%ld",&a,&b)!=EOF)
adjl[a][ ++adjl[a][0] ]=b;
match=0;
}
bool crosspath(long k)
{
for (long i=1;i<=adjl[k][0];i++)
{
long j=adjl[k][i];
if (!used[j])
{
used[j]=true;
if (mat[j]==0 || crosspath(mat[j]))
{
mat[j]=k;
return true;
}
}
}
return false;
}
void hungary()
{
for (long i=1;i<=n1;i++)
{
if (crosspath(i))
match++;
memset(used,0,sizeof(used));
}
}
void print()
{
fprintf(fo,"%ld",match);
fclose(fi);
fclose(fo);
}
int main()
{
readfile();
hungary();
print();
return 0;
}
Horcroft-Karp
#include<stdio.h>
#include<queue>
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
#define eps 1e-6
const int MAXN=3005;
const int INF=1<<28;
int g[MAXN][MAXN];
int Mx[MAXN],My[MAXN];// Mx[i]表示xi對應的匹配,My[i]表示yi對應的匹配.
int Nx,Ny;
int dx[MAXN],dy[MAXN],dis;// 層的概念,即在BFS中的第幾層.
bool vst[MAXN];
struct Node1
{
int x,y,s;
}guests[MAXN];
struct Node2
{
int x,y;
}um[MAXN];
double distance(Node1 a,Node2 b)
{
double x=a.x-b.x;
double y=a.y-b.y;
return sqrt(x*x+y*y);
}
/*
首先從所有X的未蓋點進行BFS,
BFS之後對每個X節點和Y節點維護距離標號,
如果Y節點是未蓋點那麼就找到了一條最短增廣路,
BFS完之後就找到了最短增廣路集,
隨後可以直接用DFS對所有允許弧(dist[y]=dist[x]+1,
可以參見高流推進HLPP的實現)進行類似於匈牙利中尋找增廣路的操作,
這樣就可以做到O(m)的複雜度。
*/
bool searchP()
{
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1)//將未匹配x集合中元素入隊列
{
Q.push(i);
dx[i]=0;
}
while(!Q.empty())
{
int u=Q.front();
Q.pop();
if(dx[u]>dis) break;
for(int v=0;v<Ny;v++)
if(g[u][v]&&dy[v]==-1)
{
dy[v]=dx[u]+1;
if(My[v]==-1) dis=dy[v];
else
{
dx[My[v]]=dy[v]+1;
Q.push(My[v]);
}
}
}
return dis!=INF;
}
bool DFS(int u)
{
for(int v=0;v<Ny;v++)
if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
{
vst[v]=1;
if(My[v]!=-1&&dy[v]==dis) continue;
if(My[v]==-1||DFS(My[v]))
{
My[v]=u;
Mx[u]=v;
return 1;
}
}
return 0;
}
int HK()
{
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP())
{
memset(vst,0,sizeof(vst));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1&&DFS(i)) res++;
}
return res;
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
int n,m,t,i,j;
int T,iCase=0;
scanf("%d",&T);
while(T--)
{
iCase++;
scanf("%d",&t);
scanf("%d",&m);
for(i=0;i<m;i++)
scanf("%d%d%d",&guests[i].x,&guests[i].y,&guests[i].s);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d%d",&um[i].x,&um[i].y);
Nx=m;Ny=n;
memset(g,0,sizeof(g));
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(distance(guests[i],um[j])/guests[i].s-t<eps)
{
g[i][j]=1;
}
}
}
printf("Scenario #%d:\n%d\n\n",iCase,HK());
}
return 0;
}