洛谷P1330 封锁阳光大学

题目链接:https://www.luogu.org/problem/P1330

题意:一个有n(1000)个点m(10000)条边的无向图,要封锁该图使得每条边都不能用,将一个河蟹部署在点上可使它的相邻边都报废,但相邻的两点不能够同时部署河蟹,求问是否能封锁整个图,如果能的话最少需要多少河蟹

分析:先看不能的情况,画图稍微分析一下就可以发现只要有奇环就无法封锁。

然后因为相邻两点不能同时部署,那我们就可以考虑染色了,且一张图要么不能染(奇环),能染的话肯定也只有两种情况,比较较小的即可,奇环的寻址可以直接在找环时判断,因为偶环的话第一次到达和第二次到达染的色是相同的,而奇环不同

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+7;
const int N=1e5+7;
const ll inf=0x3f3f3f3f;
#define mem0(a) memset(a,0,sizeof(a))
int nxt[N];
int head[N];
int to[N];
int cnt;
bool used[maxn];
int sum[2];
int col[maxn];
void add(int u,int v){
    cnt++;
    to[cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
bool dfs(int nd,int color){
    if(used[nd]){
        if(col[nd]==color){ 
            return true;
        }
        return false;//其实就是奇环不满足 
    }
    used[nd]=true;
    col[nd]=color;
    sum[color]++;
    for(int i=head[nd];i;i=nxt[i]){
        if(!dfs(to[i],color^1)) return false;//不能继续染色了 
    }
    return true;//说明可以继续染色下去 
}
int main(){
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        if(used[i])continue;//这个点在之前已经遍历过了 
        sum[0]=sum[1]=0;
        if(!dfs(i,0)){
            printf("Impossible");
            return 0;//直接跳出
        }
        ans+=min(sum[0],sum[1]);//把每个联通子图的最少河蟹数加上 
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/qingjiuling/p/11508252.html