洛谷P1418 选点问题

P1418 选点问题

  •  
  • 74通过
  • 240提交
  • 题目提供者tinylic
  • 标签云端
  • 难度普及+/提高
  • 时空限制1s / 128MB

 提交  讨论  题解  

最新讨论更多讨论

  • 非常重要!!
  • 90分的点这里

题目描述

给出n个点,m条边,每个点能控制与其相连的所有的边,要求选出一些点,使得这些点能控制所有的边,并且点数最少。同时,任意一条边不能被两个点控制

输入输出格式

输入格式:

第一行给出两个正整数n,m

第2~m+1行,描述m条无向边

每行给出x,y,表示一条无向边(x,y)

输出格式:

输出最少需要选择的点的个数,如果无解输出“Impossible”(不带引号)

输入输出样例

输入样例#1

7 5

1 2

1 3

5 6

6 7

1 2

输出样例#1

2

说明

【数据范围】

对于30%的数据1<=n<=100

对于100%的数据1<=n<=1000

m<=n^2

不保证图连通

【题目来源】

tinylic改编

分析:其实也没啥好分析的......对于每一个点,我们给他染色,这个点所连到的点必须不能被染色,要是已经被染色了,则输出Impossible,很好理解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int n, m,head[100010],nextt[2000020],to[2000020],tot,vis[100010],col[100010],sum[3],ans;

void add(int x, int y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

bool dfs(int u, int c)
{
    //printf("%d\n", u);
    sum[c]++;
    col[u] = c;
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = nextt[i])
    {
        int v = to[i];
        if (vis[v] && col[v] == col[u])
            return false;
        else
            if (!vis[v] && !dfs(v, 3 - c))
                return false;
    }
    return true;
}

int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
        add(b, a);
    }
    for (int i = 1; i <= n; i++)
        if (!vis[i])
        {
        sum[1] = sum[2] = 0;
        if (!dfs(i, 1))
        {
            printf("Impossible");
            return 0;
        }
        ans += min(sum[1], sum[2]);
        }
        printf("%d\n", ans);

    return 0;
}

 

posted @ 2017-06-28 22:28  zbtrs  阅读(220)  评论(0编辑  收藏  举报