看到一个讲得很好的:二分图的最大匹配,完美匹配,匈牙利算法

还有一个特别详细的:matching

 

 

uva,10080

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;
const int maxn=110;
int n,m,s,v;
int pos;


struct Point
{
    double x,y;
    void read()
    {
        scanf("%lf%lf",&x,&y);
    }
}p[maxn],q[maxn];

double dist(Point a,Point b)
{
    double dx=a.x-b.x;
    double dy=a.y-b.y;
    return sqrt(dx*dx+dy*dy);
}

struct Edge
{
    int from,to;
    Edge(){}
    Edge(int a,int b):from(a),to(b){}
}E[maxn*maxn];

vector<Edge> edges;  //记录边
vector<int> G[maxn];  //记录从i出发的遍的编号
int matching[maxn+5];
bool check[maxn+5];
typedef vector<int>::iterator iterator_t;


bool dfs(int u)
{
    for(iterator_t it=G[u].begin();it!=G[u].end();it++)
    {
        int v=edges[*it].to;
        if(!check[v])
        {
            check[v]=true;
            if(matching[v]==-1 || dfs(matching[v]))
            {
                matching[v]=u;   //显示v与u匹配
                return true;   //加上matching[u]=v是错的,因为matching[u]
//是在u之前与u匹配的点,命为w,这样覆盖了w,下次经过u,w这一条匹配
//边的时候就会出错。
//!!!!!!!注意当二分匹配的两部分点的编号不一样的时候是对的。
//也可以分拆问题,一个区间段是一个类型,然后匹配;
            }
        }
    }
    return false;
}

int hungarian()
{
    int ans=0;
    memset(matching,-1,sizeof(matching));
    for(int u=0;u<n;++u)
    {//if(matching[u]==-1)是错的,因为增广路径是可以经过已经匹配的点
 
            memset(check,false,sizeof(check));
            if(dfs(u))
                ++ans;
    }
    return ans;
}

int main()
{
    while(~scanf("%d%d%d%d",&n,&m,&s,&v))
    {
        for(int i=0;i<n;i++)
        {
            G[i].clear();
            p[i].read();
        }
        
        for(int i=0;i<m;i++)
        {
            q[i].read();
        }
        edges.clear();
        pos=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(dist(p[i],q[j])<=s*v)
                {
                    G[i].push_back(pos);
                    E[pos]=Edge(i,j);
                    edges.push_back(E[pos]);
                    pos++;
                }
            }
        }
        printf("%d\n",n-hungarian());
    }
    return 0;
}

 

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <vector>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 const int maxn=110;
10 int n,m,s,v;
11 int pos;
12 
13 
14 struct Point
15 {
16     double x,y;
17     void read()
18     {
19         scanf("%lf%lf",&x,&y);
20     }
21 }p[maxn],q[maxn];
22 
23 double dist(Point a,Point b)
24 {
25     double dx=a.x-b.x;
26     double dy=a.y-b.y;
27     return sqrt(dx*dx+dy*dy);
28 }
29 
30 vector<int> G[maxn];
31 int matching[maxn+5];
32 bool check[maxn+5];
33 typedef vector<int>::iterator iterator_t;
34 
35 
36 bool dfs(int u)
37 {
38     for(int i=0;i<G[u].size();i++)
39     {
40         int v=G[u][i];
41         if(!check[v])
42         {
43             check[v]=true;
44             if(matching[v]==-1 || dfs(matching[v]))
45             {
46                 matching[v]=u;
47                 return true;
48             }
49         }
50     }
51     return false;
52 }
53 
54 int hungarian()
55 {
56     int ans=0;
57     memset(matching,-1,sizeof(matching));
58     for(int u=0;u<n;++u)
59     {
60             memset(check,false,sizeof(check));
61             if(dfs(u))
62                 ++ans;
63     }
64     return ans;
65 }
66 
67 int main()
68 {
69     while(~scanf("%d%d%d%d",&n,&m,&s,&v))
70     {
71         for(int i=0;i<n;i++)
72         {
73             G[i].clear();
74             p[i].read();
75         }
76         
77         for(int i=0;i<m;i++)
78         {
79             q[i].read();
80         }
81         for(int i=0;i<n;i++)
82         {
83             for(int j=0;j<m;j++)
84             {
85                 if(dist(p[i],q[j])<=s*v)
86                 {
87                     G[i].push_back(j);
88                 }
89             }
90         }
91         printf("%d\n",n-hungarian());
92     }
93     return 0;
94 }
更简单的临接表重写了

相关文章: