洛谷1330封锁阳光大学——图的染色

题目:https://www.luogu.org/problemnew/show/P1330

可以想到每条边必有一段“封锁”而另一端必不“封锁”。

1.进一步想想,只要确定该边一端的状态,就能确定其另一端的状态,再由另一端影响别的点。

 所以同一连通块中必然只有确定的两种方案!

2.且这两种方案中,一种的封锁的点必是另一种的未封锁的点。

所以可以将点染成两种颜色来计数!需要注意的是每次加该连通块中数量少的颜色,不需要不同的连通块之间还保持相同颜色。

而且注意遍历边,而非未染色的点,以防只有自己一个点的连通块。

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,m,col[10005],ca,cb,s,x,y,xnt,nex[10005];
struct Node{
    int next,to,from;
}edge[200005];
bool flag;
void add(int x,int y)
{
    xnt++;
    edge[xnt].next=nex[x];
    edge[xnt].from=x;
    edge[xnt].to=y;
    nex[x]=xnt;
}
void co(int a)
{
    for(int i=nex[a];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(col[v]==col[a])
        {
            printf("Impossible");
            exit(0);
        }
        if(col[v])continue;
        col[v]=-col[a];
        if(col[v]==1)ca++;
        else cb++;
        co(v);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=2*m;i++)
        if(!col[edge[i].from]&&!col[edge[i].to])
        {
            col[edge[i].from]=1;
            ca=1;cb=0;
            co(edge[i].from);
            s+=min(ca,cb);
        }
    printf("%d",s);
    return 0;
}

 

posted on 2018-01-17 22:47  Narh  阅读(122)  评论(0编辑  收藏  举报

导航