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.

浙公网安备 33010602011771号