kuangbin专题十 HDU2389(Hopcroft-Carp的算法模板)

题意:
第一行T表示多少组数,第二行t代表还有多少时间开始下雨,然后是 N个访客,接下来N行是 每个访客的位置(x1,y1)和他的移动速度,接下来M行 代表雨伞数目,接下来M行表示各个雨伞的位置(x2,y2),问在下雨前 最多有多少人能够拿到雨伞(两个人不能共用一把伞)。
题解:
我用匈牙利跑的结果超时了,然后看题解才知道这道题是Hopcroft-Carp算法的模板题,然后就跑过去学这个算法了,结果挺失望的,一,可能是我自身的找资料能力不足,找不到好的学习资料,导致我只能留着这玩意到时候再学,现在先用着别人给的模板先。二,就是看了很多的博客基本都是说几句话就给你模板就算了,说的也是不太仔细的,很是无奈啊,模板基本都是一样的。这个Hopcroft-Carp算法的时间复杂度为O(sqrt(n)*m)。
然后我看的博客解释算多的,可以求参考一下,但是还是不够仔细。
http://blog.csdn.net/wall_f/article/details/8248373
http://blog.csdn.net/u014261987/article/details/41381733
https://www.cnblogs.com/penseur/archive/2013/06/16/3138981.html
好了,上模板。

#include
#include
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN=3000+7;
struct point
{
    double x,y,s;
}a[MAXN],b[MAXN];
bool map[MAXN][MAXN];
bool vis[MAXN];
int dx[MAXN],dy[MAXN];/*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号,还有就是这里就是bfs找增广路用的数组 对于u-->v可达就有dy[v] = dx[u] + 1 */
int cx[MAXN],cy[MAXN];
int dis;
int n,T,m;
bool searchpath()
{
    queue<int>q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=1;i<=n;i++)
    {
        //cx[i]表示左集合i顶点所匹配的右集合的顶点序号
        if(cx[i]==-1)
        {
            //将未遍历的节点 入队 并初始化次节点距离为0
            q.push(i);
            dx[i]=0;
        }
    }
    //广度搜索增广路径
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(dx[u]>dis) break;
        //取右侧节点,所以用m。 
        for(int v=1;v<=m;v++)
        {
            //右侧节点的增广路径的距离 
            if(map[u][v]&&dy[v]==-1)
            {
                dy[v]=dx[u]+1;//v对应的距离 为u对应距离加1
                if(cy[v]==-1) dis=dy[v];
                else
                {
                    dx[cy[v]]=dy[v]+1;
                    q.push(cy[v]);
                }
            }
        }
    }
    return dis!=INF;
}
 //寻找路径 深度搜索
int dfs(int u)
{
    for(int v=1;v<=m;v++)
    {
        //如果该点没有被遍历过 并且距离为上一节点+1 
        if(map[u][v]&&!vis[v]&&dy[v]==dx[u]+1)
        {
            //对该点染色,即是进行标记   
            vis[v]=true;
            if(cy[v]!=-1&&dy[v]==dis)
            continue;
            if(cy[v]==-1||dfs(cy[v]))
            {
                cx[u]=v;
                cy[v]=u;
                return 1;
            }
        }
    }
    return 0;
}
 //得到最大匹配的数目   
int MaxMatch() 
{
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    int res=0;
    while(searchpath())
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            if(cx[i]==-1)
            res+=dfs(i);
        }           
    }
    return res;
}
int main()
{
    int t,k=1;
    scanf("%d",&t);
    while(t--)
    {
        memset(map,false,sizeof(map));
        scanf("%d",&T);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].s);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        scanf("%lf%lf",&b[i].x,&b[i].y);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(a[i].s*T>=sqrt((a[i].x-b[j].x)*(a[i].x-b[j].x)+(a[i].y-b[j].y)*(a[i].y-b[j].y)))
            map[i][j]=true;
        }
        int ans=MaxMatch();  
        printf("Scenario #%d:\n%d\n\n",k++,ans);
    }
}

你可能感兴趣的:(二分图)