图论思维题
题目连接 : https://www.luogu.org/problemnew/show/P1330
曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。
询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
输入输出格式
输入格式:
第一行:两个整数N,M
接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。
输出格式:
仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。
输入输出样例
说明
【数据规模】
1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。
ac代码 :
#include<bits/stdc++.h> using namespace std; typedef struct W_W{ int to; int next; }miao; miao x[200020]; int head[200020]; int cnt; void add(int a,int b){ x[cnt].to=b; x[cnt].next=head[a]; head[a]=cnt++; } int se[200020]; int biao[200020]={0}; int sum[2]; int dfs(int start,int color){ if(biao[start]==1&&se[start]==color){ return 1; } biao[start]=1; if(se[start]==-1){ se[start]=color; } else if(se[start]!=color){ return -1; } sum[color]++; for(int i=head[start];i!=-1;i=x[i].next){ if(dfs(x[i].to,1-color)==-1){ return -1; } } return 1; } int main(){ int n,m; memset(head,-1,sizeof(head)); scanf("%d %d",&n,&m); cnt=0; for(int i=1;i<=m;i++){ int a,b; scanf("%d %d",&a,&b); add(a,b); add(b,a); } memset(se,-1,sizeof(se)); int he=0; for(int i=1;i<=n;i++){ sum[0]=0; sum[1]=0; if(biao[i]==0){ if(dfs(i,0)==1){ he+=min(sum[0],sum[1]); } else{ printf("Impossible\n"); return 0; } } } printf("%d\n",he); return 0; }
大致思路 :
因为每条路只要选一个端点即可(不能选两个因为如果一条边选两个的话就会挨着不符合题意),接下来就是相邻的点不能同时选择,所以产生了一个想法,选择一个点 把他标记为 1
然后把他相邻的所有点都标记为 0 ,如果在标记的时候发现该点被标记过而且和当前要标记的数冲突,则为不可能,然后怎样求的最小呢,因为一开始的1 是我随即选的而且 图没有冲突,
使得 1 0可以全部调换而且图依然满足要求,所以我们只要加上min(sum[ 1 ] , sum [ 0 ])即可..