yuanrh2004

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

0615 今天过了两个比较简单的知识点 ^ o ^

ps. 参考课程:acwing 算法基础课


PART 1 高精度

以除法为例,除数是一个极大的数,被除数是一个足以用int来处理的数。一般除数用string读入,后利用vector来存储(因为vector正序逆序都比较方便,高精度算法过程中一定要搞清楚当前的0位置是高位还是低位)。

vector存储大数的时候一定要记得- '0'

核心部分代码如下:


// a / b = c ... r
vector<int> div(vector<int> &a, int b, int &r ) // 通过引用r可以实现一个函数返回多个值~
{
  int t = 0;
  vector<int> c;
  for(int i = a.size() - 1; i >= 0; i--)   // 此时a的第0位是个位 除法从最高位开始
  {
    t *= 10;
    t += a[i];
    c.push_back( t / b );  // c的第0位是最高位
    t %= b;
    // 本质是模拟列竖式的过程
  }
  r = t;
  reverse(c.begin(), c.end());
  while( c.back() == 0 && c.size() > 1) c.pop_back(); // 去掉高位0
  return c;
}

PART 2 偶图与匹配

定义

偶图

官方版:若无向图G = <V,E>的结点集V能够划分为两个子集V1,V2,满足V1∩V2 = F(空集),且V1∪V2 = V(全集),使得G中任意一条边的两个端点,一个属于V1,另一个属于V2,则称G为偶图或二分图。V1和V2称为互补结点子集,偶图也可记为G = <V1,E,V2>。

简述版:可以把结点分成两个集合,每一条边一个端结点来自集合1,一个端结点来自集合2。

匹配

通过定义可以意会一下染色法

匹配的定义是:偶图存在V1 -> V2的单射f,使得任意 v ∈ V1 都有( v, f(v) ) ∈ E
因为要能够“匹配”,一条边的两个端点一定要来自不同的集合。

问题

问题1 判断是否是二分图

这里只介绍染色法判断二分图的方法,利用dfs的思路:

bool dfs(int v, int color)
{ 
  c[v] = color; // 将v结点染色成color
  for(int i = h[v]; i != - 1; i = ne[i]) // 遍历i结点的边
  {
    int j = e[i];
    if( !color[j] )   // 如果j没有被访问过
    { if(!dfs(j, 3 - color))  return false;}
    if ( color[j] == color )  return false;
  }
  return true;
}

在主函数中,利用for循环遍历每一个点,如果没有被先前的点访问过则进入dfs。利用flag来存储是否有返回false,只有flag值一直为初值,才说明是偶图。

问题2 寻找最大匹配数

已知是二分图,找v1到v2的最大匹配。

重点:维护match、st两个数组,match[j]来存储v2中点j所匹配的集合v1中的点;st数组来存储该点是否已被“本轮”匹配使用过。( 对本轮的理解也很重要,是不管之前有没有匹配过的,之前是否匹配过通过match来指示。


bool find(int v1)
{
  for(int i = h[v1]; i != -1; i = ne[i])
  {
    int j = v[i];
    if( !st[j] && (match[j] == 0 || find(match[i])) )
    {
        st[j] = true;
        match[j] = v1;
        return true;
    }
  }
  return true;
}
   

在主函数中,遍历v1集合中的所有点,每次循环都要重新将st数组赋值为0.

posted on 2025-06-19 09:37  yuanrh2004  阅读(15)  评论(0)    收藏  举报