luogu P1418 选点问题

题目描述

给出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改编

黑白染色,有多个联通块

#include<cstdio>
#include<queue>
#include<cstdlib>
using namespace std;

#define N 100003
struct node{
    int v,next;
}edge[N*10];
int head[N],n,m;int num=0;
int vis[N];
void add_edge(int x,int y)
{
    edge[++num].v=y,edge[num].next=head[x];head[x]=num;
}

int ans,ans1,ans2;
void dfs(int x)
{
    if(vis[x]==1)ans1++;
    else if(vis[x]==2)ans2++;
    for(int i=head[x];i;i=edge[i].next)
    {
        int v=edge[i].v;
        if(vis[x]==vis[v])
        {
            puts("Impossible");exit(0);
        }
        if(!vis[v])
        {
            vis[v]=3-vis[x];
            dfs(v);
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int a,b;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        add_edge(b,a);
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            ans1=ans2=0;
            dfs(i);
            ans+=min(ans1,ans2);
        }
    }
    printf("%d\n",ans);
    return 0;
}
时间: 2024-08-25 22:41:41

luogu P1418 选点问题的相关文章

P1418 选点问题(黑白染色)

P1418 选点问题 题目描述 给出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 说明 [数

洛谷P1418

P1418 选点问题 74通过 240提交 题目提供者tinylic 标签云端 难度普及+/提高 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 非常重要!! 90分的点这里 题目描述 给出n个点,m条边,每个点能控制与其相连的所有的边,要求选出一些点,使得这些点能控制所有的边,并且点数最少.同时,任意一条边不能被两个点控制 输入输出格式 输入格式: 第一行给出两个正整数n,m 第2~m+1行,描述m条无向边 每行给出x,y,表示一条无向边(x,y) 输出格式: 输出最少需

luogu题解 UVA1615 【Highway】

题目链接: https://www.luogu.org/problemnew/show/UVA1615 分析: 首先这里的距离是欧几里得距离而不是曼哈顿距离. 然后我们对于每个点,求出在公路上保持D范围内最远的两个端点,这两个端点构成一个区间,我们要做的就是选出尽量少的点使所有区间至少有一个点,就是典型的区间选点问题. 怎么做呢?把所有区间右端点从小到大排序,如果右端点相同左端点小的在前面. 达到贪心的目的,我们设一个pos=-inf,然后遍历所有区间,如果pos>该区间左端点,cnt+1,po

luogu P3799 妖梦拼木棒

二次联通门 : luogu P3799 妖梦拼木棒 /* luogu P3799 妖梦拼木棒 用一个桶存下所有的木棒 美剧两根短的木棒长度 后随便乘一乘就 好了.. */ #include <algorithm> #include <cstdio> #define Mod 1000000007 #define Max 5000 void read (int &now) { now = 0; register char word = getchar (); while (wo

[luogu P1967][NOIp2013]P1967 货车运输

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z

luogu 3126 回文的路径

https://www.luogu.org/problem/show?pid=3126 考虑dp,从两头走到中间. f[i][j][k][l]表示从左上角走到(i,j),从右下角走到(k,l),路径长度相等,所经过路径相同的方案数. 方程不再赘述. 考虑步数要相同,所以只要枚举步数和行就好. f[i][j][k]表示第一个点在第j行,第2个点在第k行,走i步的方案数. 所以得出方程f[i][j][k]=(f[i-1][j-1][k]+f[i-1][j][k+1]+f[i-1][j-1][k+1]

luogu P2018 消息传递

二次联通门 : luogu P2018 消息传递 /* luogu P2018 消息传递 树形dp 原来用优先队列做了一下, T了俩点 MMP 去看正解.. 复杂度一样好不好.. 每次到达一个点,记录其子树中所有的dp值 优先向大的一边转移 */ #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define INF 1e8 const int BUF

luogu P1966 火柴排队

二次联通门 : luogu P1966 火柴排队 /* luogu P1966 火柴排队 神TM逆序对... noip怎么这么坑啊.. 暴力都没得打 此题模拟考试时爆了0 做法 将A数组排序,由于B数组与A数组是一一对应的 那么B数组的位置也会发生相应的变化 此时B数组逆序数对数即为答案 */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 123123123; cha

luogu P1941 飞扬的小鸟

二次联通门 : luogu P1941 飞扬的小鸟 /* luogu P1941 飞扬的小鸟 dp 向上飞是完全背包,向下掉就是01背包 分情况讨论一下 最后合并一下 */ #include <cstdio> #include <iostream> #include <cstring> const int BUF = 123123123; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (