zoukankan      html  css  js  c++  java
  • 【u005】封锁阳光大学

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】
    曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。 询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
    【输入格式】
    第一行:两个整数N,M 接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。
    【输出格式】
    如果不能够对大学进封锁,则输出Impossible,否则输出所需要的最小河蟹数目。
    【数据规模】
    1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。

    Sample Input1
    3 3
    1 2
    1 3
    2 3

    Sample Output1
    Impossible

    Sample Input2
    3 2
    1 2
    2 3
    Sample Output2
    1

    【题解】

    简单的方法是对所有点进行染色。
    这里写图片描述
    如上图。在相同的颜色处放河蟹。即可占据所有的道路。且不会发生冲突。即相邻点染成不同的颜色。
    然后要求最小。就要看在0处放河蟹放得比较少还是在1处会放得比较少。取其中的较小值即可。
    然后可能会有多个子图的情况。注意一下即可。
    染色可以用广搜进行。顺便可以判断会不会出现impossible的情况。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <stdlib.h>
    
    struct node//很久没打链表了。练一下。
    {
        int en;
        node *next;
    };
    
    int n, m,color[10001],dl[10001],final_ans = 0;//color[]是给每个点染的颜色。
    node *head[10001],*tail[10001];//表示邻接表的头结点和尾节点。
    bool bo[10001] = { 0 };//判断某个点是否染色过。
    
    void input_data();
    
    void add(int,int);
    
    void get_ans();
    
    int bfs(int);
    
    void output_ans();
    
    int main()
    {
        //freopen("F:\rush.txt", "r", stdin);
        //freopen("F:\rush_out.txt", "w", stdout);
        input_data();
        get_ans();
        output_ans();
        return 0;
    }
    
    void output_ans()//输出最后的答案。
    {
        printf("%d", final_ans);
    }
    
    int bfs(int key)//从key点开始广搜进行染色。
    {
        bo[key] = true;
        color[key] = 0;
        int h = 0, t = 1;
        dl[1] = key;//加入队列
        while (h != t)
        {
            h++;//取出头结点
            int x = dl[h];
            node *temp = head[x]->next;//寻找其出度。是双向边。
            while (temp != NULL)
            {
                int y = temp->en;
                if (!bo[y])//如果之前没有染色过
                {
                    color[y] = 1 - color[x];//给其染上和x不同的颜色
                    bo[y] = true;//标记它已经染色过
                    t++;//然后把它加入到队列中,一是为了继续染色。而是为了判断它和它的邻点是否冲突。
                    dl[t] = y;
                }
                else
                    if (color[y] == color[x])//如果出度已经染过色且颜色发生冲突。则输出不可能
                    {
                        printf("Impossible");
                        exit(0);//直接结束所有的程序。
                    }
                temp = temp->next;//寻找下一个出度。
            }
        }
        int ans[2];//算出把河蟹放在颜色0和颜色1分别所需要的数目
        ans[0] = 0; ans[1] = 0;
        for (int i = 1; i <= t; i++)
            ans[color[dl[i]]]++;
        if (ans[0] > ans[1])//返回其中的较小值 bfs是一个返回Int的函数。
            return ans[1];
        else
            return ans[0];
    
    }
    
    void get_ans()
    {
        for (int i = 1; i <= n; i++)
            if (!bo[i])//因为可能出现多个子图,所以可能要多次染色。
                final_ans+=bfs(i);
    }
    
    void add(int x, int y)//加入一条边,从x->y,然后执行add(x,y),add(y,x)就变成无向边了。
    {
        tail[x]->next = new node;
        tail[x] = tail[x]->next;
        tail[x]->next = NULL;
        tail[x]->en = y;
    }
    
    void input_data()
    {
        scanf("%d%d", &n, &m);//输入n和m
        for (int i = 1; i <= n; i++)//初始化邻接表
        {
            head[i] = new node;
            head[i]->next = NULL;
            tail[i] = head[i];
        }
        for (int i = 1; i <= m; i++)//输入图的信息。
        {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            add(y, x);
        }
    }
  • 相关阅读:
    Tomcat在服务开始时去调用某个指定的类
    不能上网!???!!!
    (转载)攻击方式学习之(1) 跨站式脚本(CrossSite Scripting)
    Oracle中password file的作用及说明
    Oracle实例参数文件
    使用struts1.x标签<logic:iterate>来输出map,list
    转 remote_login_passwordfile参数和命令文件的关系
    9个重要的视图
    Oracle 关于杀掉数据库session
    Connection reset by peer: socket write error错误分析及解决
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632302.html
Copyright © 2011-2022 走看看