备战考试

考试范围
1.强连通分量
2.割点和桥,点双联通
3.DP优化
4.KM算法
5.匈牙利算法


四步走:
1.版 2.题 3.思路 4.代码


首先是强联通分量的版
如下:
1.点强连通分量
void dfs(int s,int fa){
    dfn[s]=low[s]=++dfs_clock;
    int child=0;
    for(int i=fir[s];i;i=h[i].next)
    {
        int e=h[i].e;
        if(!dfn[e])
        {
            child++; dfs(e,s);
            low[s]=min(low[s],low[e]);
            if(low[e]>=dfn[s]) iscut[s]=1;
        }
        else if(e!=fa&&dfn[s]>=dfn[e])
            low[s]=min(low[s],dfn[e]);
    }
    if(child<=1&&fa==-1) iscut[s]=0;
}
看了一下,只有三道题


一道就是裸的求割点个数


第二道就是删两个点,求最大的互不连通的图
思路是,先枚举删掉一个点,然后求出删掉哪
个点能使答案最大,开一个数组存储删掉某个
点后能使图分成多少个部分,注意就是对于根
那么需要将其-1。


第三题
题意:给一个无向图,要求毁掉两个点,使图变得不连通,图一开始是连通的
和二题差不多,就是麻烦点
首先来分析删去一个节点的效果
1.该节点不是割点,那么删除它的效果就是在原图减少一个节点
2.该节点是割点,那么删除它的效果就是是原图不联通


那么枚举删除的第一个节点,如果第一个节点是1情况,
则targin删去这个节点之后的图,找出那些点是割点,点数即是情况数
若是情况2
则除该节点本身之外的所有节点都可以满足情况


看了下题解,发现思路大致方向是对的,但不够完整
不够完整的地方在于2情况:删去一个割点
1.图被分为两个部分,每部份节点数都为1,那么这时删去任意两个节点都不能使图不连通,因此,方案数为0
2.图被分为两个部分,其中一部分节点数为1,那么这时,只能删去在另一部份节点数不为1的节点。
3.其他情况与之前分析相同


总结:注意点数为1的情况


2.边双连通分量
void dfs(int s,int fa){
    dfn[s]=low[s]=++dfs_clock;
    for(int i=fir[s];i;i=h[i].next)
    {
        int e=h[i].e;
        if(!dfn[e])
        {
            dfs(e,s); low[s]=min(low[s],low[e]);
            if(low[e]>dfn[s])
                isbridge[i]=isbridge[i^1]=1;
        }
        else if(e!=fa) low[s]=min(low[s],dfn[e]);
    }
}
也是有一道裸题,就是要套一个map
map node; 注意node不要加[]
调用就是 node["WJshiSB"]=1;
判重试!node.count("WJshiSB");
注意如果原图不连通,输出0


然后是一道求最小价值桥的题
其他没什么就是很多坑
首先,图不连通,输出0
炸不了桥,输出-1
如果ans是0,输出1


3.点双连通分量




4.边双连通分量
void dfs1(int s,int fa){
    low[s]=dfn[s]=++dfs_clock;
    for(int i=fir[s];i;i=h[i].next)
    {
        int e=h[i].e;
        if(!dfn[e])
        {
            dfs1(e,s); low[s]=min(low[s],low[e]);
            if(low[e]>dfn[s])
                isbridge[i]=isbridge[i^1]=1;
        }
        else if(s!=fa) low[s]=min(low[s],dfn[e]);
    }
}
void dfs2(int s,int id){
    low[s]=id; vis[s]=1;
    for(int i=fir[s];i;i=h[i].next)
    {
        int e=h[i].e;
        if(vis[e]) continue;
        if(isbridge[i])
            dfs2(e,++level);
        else dfs2(e,id);
    }
}
对于点双分和边双分的题,最常见的
做法就是缩点,然后统计一些什么出
度或入度为0的题




5.有向图的双连通分量
void dfs(int s){
    dfs[s]=low[s]=++dfs_clock;
    stk.push(s);
    for(int i=fir[s];i;i=h[i].next)
    {
        int e=h[i].e;
        if(!dfn[e])
            {dfs(e); low[s]=min(low[s],low[e]);}
        else if(!mark[e])
            low[s]=min(low[s],dfn[e]);
    }
    if(dfn[s]==low[s])
    {
        scnt++; int t=-1;
        while(t!=s)
        {
            e=stk.top(); stk.pop();
            mark[e]=scnt;
        }
    }
}
题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,
要求至少要有2条独立的路可以走。现已有m条路,求至
少要新建多少条路,使得任何两个牧场之间至少有两条
独立的路。两条独立的路是指:没有公共边的路,但可
以经过同一个中间顶点。
求一个边双分缩点,把叶子节点两两相连即可
然后答案就是叶子节点的个数(num+1)>>1;




题意:各学校之间有单向的网络,每个学校得到一套软件后,可
以通过单向网络向周边的学校传输,问题1:初始至少需要向多
少个学校发放软件,使得网络内所有的学校最终都能得到软件。
问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软
件后,经过若干次传送,网络内所有的学校最终都能得到软件。


求一个有向图双分缩点
问题1就是求缩点后入度为0的点个数
问题2就是求缩点后入度为0和出度为0的点个数的较大值


题目大意:如果v点能够到的点,反过来能够到达v点,则称这个点为sink点,输出所有的sink点
解题思路:有向图双分缩点,然后出度为0的连通里面的点就是sink点

你可能感兴趣的:(考试题目,考试总结)