洛谷 P1330 封鎖陽光大學題解

題目描述

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

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

詢問:最少須要多少隻河蟹,能夠封鎖全部道路而且不發生衝突。ios

輸入格式

第一行:兩個整數N,M數組

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

輸出格式

僅一行:若是河蟹沒法封鎖全部道路,則輸出「Impossible」,不然輸出一個整數,表示最少須要多少隻河蟹。code

輸入輸出樣例

輸入 #1
3 3
1 2
1 3
2 3
輸出 #1
Impossible
輸入 #2
3 2
1 2
2 3
輸出 #2
1

說明/提示

【數據規模】orm

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


題解

本題其實是一道二分圖的題目。blog

若是咱們把圖中U、V兩個集合中的全部連線都用河蟹斷開,就達到了題目要求。要判斷圖中的二分圖,只須要相似01迷宮進行BFS遍歷染色便可。在染色的過程當中,若是發現連線的另外一個端點未染色,就用和當前端點不一樣的顏色染色,要是已經染色且和當前節點顏色相同,就說明構成循環圈,不能構成二分圖,相似下圖的狀況。ci

代碼以下:

  1 #include <iostream>
  2 #include <math.h>
  3 #include <stdio.h>
  4 #include <algorithm>
  5 #include <string.h>
  6 
  7 using namespace std;
  8 
  9 const int MAXN = 100005;
 10 int first[MAXN], n, m, en, color[MAXN], f[2], u, v; //f統計不一樣顏色節點數 
 11 int front, rear; 
 12 bool vis[MAXN]; 
 13 int ans;
 14 
 15 struct edge
 16 {
 17     int zhongdian, changdu;
 18     int next;
 19 };
 20 
 21 edge ed[MAXN]; 
 22 
 23 void add_edge(int s, int e, int d) 
 24 {
 25     en++; 
 26     ed[en].next = first[s]; 
 27     first[s] = en;
 28     ed[en].zhongdian = e;
 29     ed[en].changdu = d;
 30 }
 31 
 32 struct Node
 33 {
 34     int x, y;
 35     int step;
 36 };
 37 Node q[MAXN];
 38 
 39 int bfs(int a)
 40 {
 41     Node now, next;
 42     now.x = a;
 43     vis[a] = 1;
 44     color[a] = 1;
 45     f[0] = 0;
 46     f[1] = 1;
 47     front = rear = 0;
 48     q[rear] = now;
 49     rear++;
 50     while(front < rear)
 51     {
 52         now = q[front++];
 53         for(int i = first[now.x]; i; i = ed[i].next)
 54         //first[now]:當前點的第一條邊;ed[i].next:下一個訪問的點  
 55         {
 56             if(color[ed[i].zhongdian] != -1)
 57             {
 58                 if(color[ed[i].zhongdian] == color[now.x])
 59                 {
 60                     cout << "Impossible" << endl;
 61                     return -1;
 62                 }
 63             } 
 64             else
 65             {
 66                 color[ed[i].zhongdian] = (color[now.x] + 1) % 2;
 67                 q[rear].x = ed[i].zhongdian;
 68                 rear++;
 69                 f[color[ed[i].zhongdian]]++;
 70             }
 71         } 
 72     }
 73     ans += min(f[0], f[1]);
 74 }
 75 
 76 int main()
 77 {
 78     cin >> n >> m;
 79     for(int i = 1; i <= n; i++)
 80     {
 81         color[i] = -1; //初始化  
 82     }
 83     for(int i = 1; i <= m; i++)
 84     {
 85         cin >> u >> v;
 86         add_edge(u, v, 0);
 87         add_edge(v, u, 0);
 88     }
 89     for(int i = 1; i <= n; i++)
 90     {
 91         if(color[i] == -1)
 92         {
 93             if(bfs(i) < 0)
 94             {
 95                 return 0;
 96             }
 97         } 
 98     }
 99     cout << ans << endl;
100     
101     return 0;
102 }

代碼中的f數組是用來統計黑白兩種染色點的個數的,本題所求的最小河蟹數就是兩種染色點個數的最小值。

相關文章
相關標籤/搜索