C++ P1330 封鎖陽光大學
阿新 • • 發佈:2018-11-19
題目描述
曹是一隻愛刷街的老曹,暑假期間,他每天都歡快地在陽光大學的校園裡刷街。河蟹看到歡快的曹,感到不爽。河蟹決定封鎖陽光大學,不讓曹刷街。
陽光大學的校園是一張由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,任意兩點之間最多有一條道路。
題目連結:https://www.luogu.org/problemnew/show/P1330
個人思路:
- 首先,將存在河蟹的點視為被染色的點,就可以考慮到二分圖染色.
- 由於資料不保證此圖為聯通圖,需要遍歷所有點進行BFS,當然也需要vis陣列儲存某個點是否被訪問過的資料.
- 在每一個聯通子圖的BFS過程中,取較小的一個進行返回即可(因為只要二分圖中一半的點被染色,該題題意即符合).
- 最終,對所有聯通子圖的BFS結果進行求和即可.
#include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; const int N=10005,M=200005; int n,m,cnt=0,head[N],cl[N],vis[N],ansA=0; struct Edge{ int v,w,nxt; }e[M]; void addEdge(int u,int v,int w){ e[++cnt].v=v; e[cnt].w=w; e[cnt].nxt=head[u]; head[u]=cnt; } int ans[2]{0,0}; int bfs(int x){ queue<int> q; q.push(x); while(!q.empty()){ int nowValue=q.front();q.pop(); for(int i=head[nowValue];i;i=e[i].nxt){ int nowV=e[i].v; if(cl[nowV]==-1){ cl[nowV]=cl[nowValue]^1; ans[cl[nowV]]++; q.push(nowV); } if(cl[nowV]==cl[nowValue]){ return -1; } } } return min(ans[0],ans[1]); } int main(){ memset(cl,-1,sizeof(cl)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int ta,tb; scanf("%d%d",&ta,&tb); addEdge(ta,tb,1); addEdge(tb,ta,1); } for(int i=1;i<=n;i++){ if(cl[i]==-1){ cl[i]=1; ans[1]++; //cout<<"bfs:"<<i<<endl; int tempAns=bfs(i); if(tempAns==-1){ printf("Impossible\n"); return 0; } ansA+=tempAns; memset(ans,0,sizeof(ans)); } } printf("%d\n",ansA); return 0; }