1. 程式人生 > >luogu P1330 封鎖陽光大學 x

luogu P1330 封鎖陽光大學 x

printf 不讓 方案 無法 scanf 天都 out log ios

P1330 封鎖陽光大學

題目描述

曹是一只愛刷街的老曹,暑假期間,他每天都歡快地在陽光大學的校園裏刷街。河蟹看到歡快的曹,感到不爽。河蟹決定封鎖陽光大學,不讓曹刷街。

陽光大學的校園是一張由N個點構成的無向圖,N個點之間由M條道路連接。每只河蟹可以對一個點進行封鎖,當某個點被封鎖後,與這個點相連的道路就被封鎖了,曹就無法在與這些道路上刷街了。非常悲劇的一點是,河蟹是一種不和諧的生物,當兩只河蟹封鎖了相鄰的兩個點時,他們會發生沖突。

詢問:最少需要多少只河蟹,可以封鎖所有道路並且不發生沖突。

輸入輸出格式

輸入格式:

第一行:兩個整數N,M

接下來M行:每行兩個整數A,B,表示點A到點B之間有道路相連。

輸出格式:

僅一行:如果河蟹無法封鎖所有道路,則輸出“Impossible”,否則輸出一個整數,表示最少需要多少只河蟹。

輸入輸出樣例

輸入樣例#1:
【輸入樣例1】
3 3
1 2
1 3
2 3

【輸入樣例2】
3 2
1 2
2 3

輸出樣例#1:
【輸出樣例1】
Impossible

【輸出樣例2】
1

說明

【數據規模】

1<=N<=10000,1<=M<=100000,任意兩點之間最多有一條道路。

思路:

  1)黑白染色

  2)利用bfs分層搜索的性質,註意要分層!!!

  3)如果一個點搜索到一個與自己同色的點,證明不存在合法方案!

  4)各個聯通塊分開累加答案!

  5)答案就是當前聯通塊內部的黑色與白色的最小值!

坑點:

  1)別信數據範圍qwq

  2)註意可能存在的好幾個聯通塊的情況!

代碼:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;

const int M = 1000010;
int n,m,tot,ans;
int head[M],a[M],steps[M],w[M],colors[5
]; bool QAQ,vis[M]; struct B{ int next,to; }t[M]; void add(int u,int v) { tot++; t[tot].to=v; t[tot].next=head[u]; head[u]=tot; } void bfs(int u) { for(int i=1;i<=n;i++) w[i]=0,steps[i]=0; int fr=0,sz=1; colors[1]=colors[2]=0; steps[1]=1; w[1]=u; a[u]=1; vis[u]=true; while(fr<sz) { fr++; int now=w[fr]; for(int i=head[now];i;i=t[i].next) { int v=t[i].to; if(a[v]==a[now]) { QAQ=false; return; } if(!vis[v]) { vis[v]=true; sz++; w[sz]=v; steps[sz]=steps[fr]+1; if(steps[sz] % 2 == 1) a[v]=1; else if(steps[sz] % 2 == 0) a[v]=2; } } } for(int i=1;i<=sz;i++) colors[a[w[i]]]++; ans+=min(colors[1],colors[2]); } int main() { scanf("%d%d",&n,&m); for(int i=1,a,b;i<=m;i++) { scanf("%d%d",&a,&b); add(a,b),add(b,a); } for(int i=1;i<=n;i++) { if(!vis[i]) { QAQ=true; bfs(i); if(!QAQ) { printf("Impossible\n"); return 0; } } } cout<<ans; return 0; }

luogu P1330 封鎖陽光大學 x