曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由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,任意两点之间最多有一条道路。
思路
用数组 f 记录当前顶点的状态,0表示未确定,1表示占领或未被占领,2表示未被占领或占领,当某一个顶点状态为1时,那么相邻顶点的状态为2,再下一层为1,以此类推,121212...,当此顶点与上一个顶点状态相同时(同为1或2),则表示冲突,即不可能。
用 数组 a[ i ][ 0 ]表示与顶点 i 相关联的边数,a[ i ] [ j ] 表示与顶点 i 相连的 第 j 条边的顶点。
用 nn 统计状态为 1 的顶点的数目,mm统计状态为2 的顶点的数目。若能占领,则取二者中的最小值为最少需要的河蟹数。
此题应注意
此题不是弱连通图,而是几个连通图。故需用计数器ans进行计算。
#include<cstdio> #include<iostream> using namespace std; const int maxn=1e4+5; int n,m,nn,mm,f[maxn],a[maxn][500]; void dfs(int h) { for(int j=1;j<=a[h][0];j++){ if(f[a[h][j]]==f[h]){ printf("Impossible\n"); exit(0); } if(!f[a[h][j]]){ f[a[h][j]]=3-f[h]; if(f[a[h][j]]==1)nn++; else mm++; dfs(a[h][j]); } } } int main() { scanf("%d%d",&n,&m); int x,y,ans=0; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); a[x][++a[x][0]]=y; a[y][++a[y][0]]=x; } for(int i=1;i<=n;i++) if(!f[i]){ f[i]=1; nn=1;mm=0; dfs(i); nn=min(nn,mm); ans+=nn; } printf("%d\n",ans); return 0; }