洛谷:P1330:封锁阳光大学


洛谷:P1330:封锁阳光大学

Table of Contents

题目

P1330:封锁阳光大学

分析

这道题其实在问一个很简单的问题:我要在路口放路障,但是有个限制:一条路的两头不能都放路障(和题意矛盾)。

我们可以这样想:

  1. 想象你在给路口贴标签:

    • 有些路口贴“要放路障”
    • 有些路口贴“不放路障”
    • 每个路口必须贴其中一种标签
  2. 规则很简单:

    • 两个相连的路口不能都贴“要放路障”
    • 但至少要有一个路口贴“要放路障”,不然这条路就没被封锁

这不就是在把路口分成两类吗?一类是“路障”,一类是“没路障”。但相连的路口必须属于不同类。

这就是二分图的本质:我们在把点分成两类,相连的点不能在同一类里。而解二分图,可以用染色法:帮我们区分这两类点。

如果发现有些点怎么都无法合理分类(比如某个环的长度是奇数),那就说明这个封锁方案是不可能的。

bool dfs(int u, int c, int& count1, int& count2)
{
    color = c;
    if (c == 1)
        count1++;
    else
        count2++;

    for (int v : graph)
    {
        if (color[v] == 0)
        {
            // 相邻节点染成相反的颜色
            if (!dfs(v, 3 - c, count1, count2)) //3-1=2, 3-2=1。切换颜色
                return false;
        }
        else if (color[v] == c)
        {
            // 如果相邻节点颜色相同,则不是二分图
            return false;
        }
    }
    return true;
}

考虑到可能存在多个通路,还要对每个(没有染色的)节点重复上述过程。累加用色最少的那个颜色的数量,就是答案。

答案

Solution

思考

为什么二分图染色可以解决这个问题?可以类比之前的“(自己的)敌人”和“(自己的)敌人的敌人”这样的关系。相邻节点肯定是“敌人”:无论如何,它们不能都放路障。而“敌人的敌人”必须和自己一样也放路障。但如果出现矛盾:一个敌人的敌人因为某种原因成了自己的敌人,那么肯定不对了。

因此,染色实际上是在将节点分成两个独立集,而路障必须放在其中一个集合中。

二分图染色有很多实际应用:

  • 课程安排问题
  • 社交网络分析
  • 资源分配优化

上一篇 下一篇