UOJ #79 一般图最大匹配

一般图最大匹配

从前一个和谐的班级,所有人都是搞OI的。有 \(n\) 个是男生,有 \(0\) 个是女生。男生编号分别为 \(1,…,n\)。

现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽。每个人至多属于一个小组。

有若干个这样的条件:第 \(v\) 个男生和第 \(u\) 个男生愿意组成小组。

请问这个班级里最多产生多少个小组?

输入格式

第一行两个正整数,\(n,m\)。保证 \(n≥2\)。

接下来 \(m\) 行,每行两个整数 \(v,u\) 表示第 \(v\) 个男生和第 \(u\) 个男生愿意组成小组。保证 \(1≤v,u≤n\),保证 \(v≠u\),保证同一个条件不会出现两次。

输出格式

第一行一个整数,表示最多产生多少个小组。

接下来一行 \(n\) 个整数,描述一组最优方案。第 \(v\) 个整数表示 \(v\) 号男生所在小组的另一个男生的编号。如果 \(v\) 号男生没有小组请输出 \(0\)。

限制与约定

\(1≤n≤500\),\(1≤m≤124750\)。



是个板子,因为细节比较复杂我就不说了(其实有的自己也搞不清楚...

放个代码吧,有一些注释

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=510;
int head[N],to[N*N],Next[N*N],cnt;
void add(int u,int v)
{
    to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int F[N],vis[N],clock,pre[N],match[N],q[N*N],l,r,f[N],typ[N],n,m;
int Find(int x){return f[x]=f[x]==x?x:Find(f[x]);}
int LCA(int x,int y)
{
    for(++clock;;std::swap(x,y))
        if(x)//防止走过
        {
            x=Find(x);//在缩掉的花朵上走
            if(vis[x]==clock) return x;
            else vis[x]=clock,x=pre[match[x]];//一次跳两步
        }
}
void shrink(int x,int y,int t)//缩花
{
    while(Find(x)!=t)//注意是根到没到
    {
        pre[x]=y,y=match[x];//走x那条链,最开始时末尾两个1类点互指
        if(typ[y]==2) typ[y]=1,q[++r]=y;//因为不知道奇环的哪个点去匹配,所以都去试试
        if(Find(x)==x) f[x]=t;//我猜加if和带花树的结构有关
        if(Find(y)==y) f[y]=t;
        x=pre[y];//往前跳
    }
}
bool path(int st)
{
    q[l=r=1]=st;
    memset(typ,0,sizeof(typ)),memset(pre,0,sizeof(pre));//点的类型和非匹配边
    for(int i=1;i<=n;i++) f[i]=i;
    while(l<=r)
    {
        int u=q[l++];
        for(int i=head[u];i;i=Next[i])
        {
            int v=to[i];
            if(typ[v]==2||Find(u)==Find(v)) continue;//已经访问的二类点或者在同一朵花中
            if(!typ[v])//不在带花树上
            {
                pre[v]=u,typ[v]=2;//成为第二类点
                if(!match[v])
                {
                    int tmp;
                    do
                    {
                        match[tmp=v]=u;
                        v=match[u];
                        match[u]=tmp;
                        u=pre[v];
                    }while(u);
                    return true;
                }
                typ[q[++r]=match[v]]=1;//成为1类点进队
            }
            else//形成了奇环
            {
                int lca=LCA(u,v);
                shrink(u,v,lca);
                shrink(v,u,lca);
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int v,u,i=1;i<=m;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    int ans=0;
    for(int i=1;i<=n;i++) ans+=(!match[i]&&path(i));//没匹配过且存在增广路
    printf("%d\n",ans);
    for(int i=1;i<=n;i++) printf("%d ",match[i]);
    return 0;
}


2018.12.24

原文地址:https://www.cnblogs.com/ppprseter/p/10170392.html

时间: 2024-10-11 04:53:23

UOJ #79 一般图最大匹配的相关文章

HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 如果C2+2==C1则这条边再某个最大匹配中 Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Submission(s): 649    Accepted Submission(s): 202

UOJ79 一般图最大匹配

题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于一个小组. 有若干个这样的条件:第 vv 个男生和第 uu 个男生愿意组成小组. 请问这个班级里最多产生多少个小组? 输入格式 第一行两个正整数,n,mn,m.保证 n≥2n≥2. 接下来 mm 行,每行两个整数 v,uv,u 表示第 vv 个男生和第 uu 个男生愿意组成小

最短路思想实现一般图最大匹配

考虑一下一般图和二分图的区别,无非就在于二分图可能出现长为奇数的环. 如何排除奇数环的影响??? 最短路 设一般图中每条可匹配边长为1,该次匹配起点为v. 根据最短路定理,我们可以知道,v在带花树上到任意一个终点(即未匹配的点)的最短距离一定为奇数,且路径上一定不存在环. 那么,用广搜的方法去贪最短路的时候,贪出来的第一条路(即最短路)一定不含环. 设[1,n]代表S型点,[n+1,2*n]代表T型点,dist[i]表示v到i的最短路上经过的点数. 设ance[i][j]表示i的dist值为j的

poj 3020 一般图最大匹配 带花树开花算法

题意: 给出一个h*w的图,每个点都是'o'或'*',最少要用多少个1*2的矩形才能把图中所有的'*'都覆盖掉. 限制: 1 <= h <= 40; 1 <= w <= 10 思路: 最小边覆盖=|V|-最大匹配 一般图最大匹配,带花树开花算法 /*poj 3020 一般图最大匹配 带花树开花算法 题意: 给出一个h*w的图,每个点都是'o'或'*',最少要用多少个1*2的矩形才能把图中所有的'*'都覆盖掉. 限制: 1 <= h <= 40; 1 <= w &l

ZOJ 3316 Game 一般图最大匹配带花树

一般图最大匹配带花树: 建图后,计算最大匹配数. 如果有一个联通块不是完美匹配,先手就可以走那个没被匹配到的点,后手不论怎么走,都必然走到一个被匹配的点上,先手就可以顺着这个交错路走下去,最后一定是后手没有路可走,因为如果还有路可走,这一条交错路,就是一个增广路,必然有更大的匹配. Game Time Limit: 1 Second      Memory Limit: 32768 KB Fire and Lam are addicted to the game of Go recently.

【UOJ 79】 一般图最大匹配 (?带花树开花)

从前一个和谐的班级,所有人都是搞OI的.有 n 个是男生,有 0 个是女生.男生编号分别为 1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于一个小组. 有若干个这样的条件:第 v 个男生和第 u 个男生愿意组成小组. 请问这个班级里最多产生多少个小组? 输入格式 第一行两个正整数,n,m.保证 n≥2. 接下来 m 行,每行两个整数 v,u 表示第 v 个男生和第 u 个男生愿意组成小组.保证 1≤v,u≤n,保证 v≠u,保证同一个条

带花树——一般图最大匹配

问题 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. 这个问题的退化版本就是二分图最大匹配. 由于二分图中不存在奇环,偶环对最大匹配并无影响(可以调整).所以增广路算法是可以顺利应用的. 在一般图中,我们还是尝试使用BFS增广路的算法. 然而一般图中还会出现奇环,在寻找增广路的时候,怎么处理奇环上的冲突? 目的就是将奇环不断地缩起来(缩花),使得整个图在使用增广算法的时候不受影响,即不会经过奇环. ? ? ? 花 ? 一朵花由一个奇环缩点而成,一朵花里面可能还会有花.

【题解】Uoj79一般图最大匹配

带花树裸题,感觉带花树强强……不会的勿看此文,解释的可能不对,只是给自己看的!!!如题,带花树即为求一般图最大匹配算法(匈牙利与dinic为二分图最大匹配).推荐论文:2015年<浅谈图的匹配算法及其应用>(长郡中学    ——陈胤伯).论文当中有对于带花树算法的详细解析,在这里只想记录一下算法的基本流程: —————————————————————————— \(id\) : 记录一个点为奇点/偶点(0偶1奇). \(fa\) : 并查集记录一个点属于哪一个点为根的花. ——————————

一般图最大匹配带花树

参考博客:http://blog.sina.com.cn/s/blog_95ec9e7401018bga.html https://www.cnblogs.com/owenyu/p/6858508.html 用Dinic实现的二分图匹配的时间复杂度其实是O(M*N^0.5),这也许能够解释为什么一般网络流算法比Hungry要快了. 另外,带花树算法的正确性的证明比较困难:而其时间复杂度是可以做到O(M*N^0.5)的 简述一下“带花树”算法吧: 它的核心思想还是找增广路.假设已经匹配好了一堆点,