• 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,任意两点之间最多有一条道路。

    Solution:

    由题意得每条边必须且有且只有一个顶点被封锁,即一条边所连向的两点不得同时被封锁,类似于二分图,so可以理解为对图染色,注意本图可能存在多个连通图,于是我们直接不停从没有被标记的点开始dfs并染色,使得相邻的点颜色不同,若某次访问到了被标记的点,则判断它的本次染色是否和本来颜色一致,不同则Impossible,否则答案就是每个连通图染色后最少的颜色个数的累加和。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define N 200005
    using namespace std;
    il int gi()
    {
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    int n,m,a,b,h[N],cnt,to[N],net[N],rs[N],sum[2],ans;
    bool vis[N];
    il void add(int u,int v)
    {
        to[++cnt]=v,net[cnt]=h[u],h[u]=cnt;
        to[++cnt]=u,net[cnt]=h[v],h[v]=cnt;
    }
    il bool dfs(int x,int c)
    {
        if(vis[x]){return rs[x]==c?1:0;}
        vis[x]=1;
        sum[rs[x]=c]++;
        bool f=1;
        for(int i=h[x];i;i=net[i])f=f&&dfs(to[i],1-c);
        return f;
    }
    int main()
    {
        n=gi(),m=gi();
        //memset(rs,-1,sizeof(rs));
        int u,v;
        for(int i=1;i<=m;i++)
        {
            u=gi(),v=gi();
            add(u,v);
        }
        for(int i=1;i<=n;i++)
        if(!vis[i]){
            sum[0]=0;sum[1]=0;
            if(!dfs(i,0)){puts("Impossible");return 0;}
            ans+=min(sum[0],sum[1]);
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    python note 19 异常处理
    python note 18 序列化模块
    python note 17 random、time、sys、os模块
    python note 16 re模块的使用
    python note 15 正则表达式
    python note 13 内置函数
    python note 12 生成器、推导式
    C++ int型负数除法取余问题
    Leetcode162. 寻找峰值
    Leetcode450. 删除二叉搜索树中的节点
  • 原文地址:https://www.cnblogs.com/five20/p/8576135.html
Copyright © 2020-2023  润新知