洛谷P1330 封锁阳光大学(图的连通,图的染色) 题解

题目来源:

点击打开链接

题目描述:

题目描述

曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。

阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。

询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。

输入输出格式

输入格式:

第一行:两个整数N,M

接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。

输出格式:

仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。

输入输出样例

输入样例#1:  复制
3 3
1 2
1 3
2 3
输出样例#1:  复制
Impossible





输入样例#2:  复制
3 2
1 2
2 3


输出样例#2:  复制
1









说明

【数据规模】

1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。


解题思路:

   1.首先图可能不连通,所以要图分成一个个连通的图来做,在每一个连通图中,因为相邻的点不能同时封锁,所以我们考虑用两种颜色染色,相邻的不能染同一种颜色,那样再取两种颜色数较小的那个,这个数就是这一个连通图需要的河蟹数,最后再把所有连通图的结果加起来就行。

   2.用dfs来判断连通图的数量,并且可以标记,在染色的时候使用bfs来进行,ans+=min(sum1,sum2)就行,最后输出ans

代码:

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
int ls[10005],lt[10005],gs;
struct newt{
    int num,ys;
}dian;
vector<int>E[10005];
void dfs(int u)
{
    lt[u]=gs;
    for(int i=0;i<E[u].size();i++)
    {
        int v=E[u][i];
        if(!lt[v]){
            dfs(v);
        }
    }
}
int main()
{
    int n,m;
    cin>>n>>m;
    memset(ls,0,sizeof(ls));
    memset(lt,0,sizeof(lt));
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        E[a].push_back(b);
        E[b].push_back(a);
    }
    gs=0;
    for(int i=1;i<=n;i++)
    {
        if(!lt[i]){
            gs++;
            dfs(i);
        }
    }
    int flag=0,ans=0;
    for(int i=1;i<=gs;i++)
    {
        int sum1=0,sum2=0;
        if(flag){
            break;
        }
        queue<newt>q;
        for(int j=1;j<=n;j++)
        {
            if(lt[j]==i){
                dian.num=j;dian.ys=1;
                q.push(dian);
                break;
            }
        }
        while(!q.empty())
        {
            if(flag)break;
            newt now=q.front();
            ls[now.num]=now.ys;
            if(now.ys==1)sum1++;
            else sum2++;
            q.pop();
            for(int j=0;j<E[now.num].size();j++)
            {
                int v=E[now.num][j];
                if(!ls[v]){
                    newt nod;
                    nod.num=v;
                    if(now.ys==1){
                        nod.ys=2;
                        q.push(nod);
                        ls[v]=2;
                    }
                    else{
                        nod.ys=1;
                        q.push(nod);
                        ls[v]=1;
                    }
                }
                else{
                    if(ls[v]==now.ys){
                        flag=1;break;
                    }
                }
            }
        }
        ans+=min(sum1,sum2);
    }
//	for(int i=1;i<=n;i++)
//	cout<<ls[i]<<" ";
    if(!flag)
    cout<<ans<<endl;
    else cout<<"Impossible"<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81019831