zoukankan      html  css  js  c++  java
  • 洛谷 P1330 封锁阳光大学题解

    题目描述

    曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。

    阳光大学的校园是一张由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,任意两点之间最多有一条道路。


    题解

    本题实际上是一道二分图的题目。

    如果我们把图中U、V两个集合中的所有连线都用河蟹断开,就达到了题目要求。要判断图中的二分图,只需要类似01迷宫进行BFS遍历染色即可。在染色的过程中,如果发现连线的另一个端点未染色,就用和当前端点不同的颜色染色,要是已经染色且和当前节点颜色相同,就说明构成循环圈,不能构成二分图,类似下图的情况。

    代码如下:

      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数组是用来统计黑白两种染色点的个数的,本题所求的最小河蟹数就是两种染色点个数的最小值。

  • 相关阅读:
    EntityFramework6.X 之Relationship
    EntityFramework6.X 之Inheritance Stategy
    EntityFramework6.X 之 Fulent
    EntityFramework6.X之DataAnnotations
    EntityFramework6.X 之 Database Initialization
    EntityFramework6.X 之DbContex
    EntityFramework6.X 之LocalDB&ConnectionString
    EntityFramework6.X之概述
    C提高_day03_玩转多级指针
    C提高_day03_二级指针内存示意图(没有比这重要的了)
  • 原文地址:https://www.cnblogs.com/zealsoft/p/11399061.html
Copyright © 2011-2022 走看看