P1330 封锁阳光大学

原题链接

分析

分析题目的限制

  • 相连两个点不能同时选
  • 要选最少的点将所有的边进行覆盖

提炼一下,我们能得到什么。

  • 二分图,通过这两个条件,这个图一定是个二分图,不然一定无解。
  • 我们选的点一定都是二分图中其中点数少的那一半。因为我们选择点互相之间不能有边。

因此,我们的思路就出来了,染色法判二分图,注意,图不一定是联通的,需要每一个连通图都是二分图。

对其中每一个二分图,我们答案加点数少的一半即可。

错点分析

其实,我看到之后,判断完二分图,我说,这不最小点覆盖问题嘛,直接跑一个匈牙利就行。

然后,我就不出意外的WA了。

原因也很简单,最小点覆盖问题,求的是选择最小的点,使得每一条边至少有一个顶点被选择,其中可能会选到,一条边的两个顶点。

这就跟题目产生很大的分歧了。

题目的要求只能选择互相之间无边的点。

AC_Code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10,M = 2e5 + 10;
int h[N],e[M],ne[M],idx;
int color[N],match[N];
bool st[N];
int n,m,res,cnt1,cnt2;

void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

bool dfs(int u,int c)
{
    color[u]=c;
    if(c==1) cnt1++;
    else cnt2++;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(!color[j])
        {
            if(!dfs(j,3-c)) return false;
        }else if(color[j]==c) return false;
    }
    return 1;
}

int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        add(a,b),add(b,a);
    }
    for(int i=1;i<=n;i++)
        if(!color[i]){
            cnt1=cnt2=0;
            if(!dfs(i,1))
            {
                puts("Impossible");
                return 0;
            }
            else res+=min(cnt1,cnt2);
        }
    cout<<res<<endl;
    return 0;
}
posted @ 2021-11-12 11:13  艾特玖  阅读(36)  评论(0)    收藏  举报