2019暑假五考Ronald(神仙结论题)

7 篇文章 0 订阅
1 篇文章 0 订阅

~目录~


题目

描述
一个国家有n个城市,城市之间连接着双向航空线路。一位疯狂的航空公司总裁Ronald Krump经常改变航班时刻表。更准确地说,他每天都做以下事情:

●选择其中一个城市

●如果该城市和某个其他城市之间之前没有航线那么在这两个城市之间创建一条航线,如果该城市和某个其他城市之间之前已有航线那么取消这条航线

例如,如果从城市5有航线通往城市1和2,但没有航线通往城市3和4,那么在Krump选择城市5并进行操作后,将有从城市5通往城市3和4的航线,但没有从城市5通往城市1和2的航线。

这个国家的公民在想,是否有一天航线图会变为完全图。换言之,当天任意两个不同的城市之间存在一条航线(直达)。写一个程序,根据当前的航线图,确定是否有可能有某一天出现这种情况,通过Krump的操作。
输入格式
第一行输入包含一个整数 N N N。表示城市的数量。城市从1到N编号。 第二行输入包含一个整数 M M M。表示当前航线的数量。 接下来M行每行包含两个不同的整数,表示一条航线连接的两个城市的编号。
输出格式
如果有一天航线图会变为完全图,那么输出“DA”。否则输出“NE”。输出均不含引号。
范围
2 ≤ N ≤ 1000 , 0 ≤ M ≤ N ∗ ( N − 1 ) 2 2≤N≤1000,0≤M≤\frac{N*(N-1)}{2} 2N1000,0M2N(N1)
样例

样例输入1
2
0
样例输出1
DA

样例输入2
3
2
1 2
2 3
样例输出2
NE

样例输入3
4
2
1 3
2 4
样例输出3
DA

思路

考试时第一眼看感觉是强联通分量(好像叫点双联通分量,但写着好像是强联通分量),如果有偶数个强联通分量,好像都行,因为2个可以,4个的没推出来;奇数个分量就不行,但如果它本身就是一个完全图,好像又错了,所以后面打了两个表,加上强联通的代码,对了五个点(一共8个点,还是绑定数据),真水啊

开始正解:
如果这个图本身就是完全图或者一条边都没有,那么肯定可以

如果这个图只有两个完全图 G 1 , G 2 G_1, G_2 G1,G2,想一想, G 2 G_2 G2中的每个点先与 G 2 G_2 G2中剩下的点断开,再融入 G 1 G_1 G1中,此时 G 1 G_1 G1肯定还是一个完全图(新点与 G 1 G_1 G1原图中的每个点都建立联系),那么循环下去,最后肯定只剩一个完全图了

如果这个图有一个完全图 G 1 G_1 G1,一个非完全图 G 2 G_2 G2,若把 G 1 G_1 G1融入 G 2 G_2 G2,按照上面的方法,最后剩下的肯定是一个不完全图;若把 G 2 G_2 G2融入 G 1 G_1 G1,那么 G 2 G_2 G2中至少都会有一个点在融入 G 1 G_1 G1时与 G 2 G_2 G2中的某一个点建立联系(什么?你说上面也会有这种情况,请搞清楚,上面建立联系的点既不属于 G 1 G_1 G1,也不属于 G 2 G_2 G2),所以最后也不是一个完全图

如果这个图有两个非完全图 G 1 , G 2 G_1,G_2 G1,G2,你想,一个完全图和一个非完全图都不可能,两个非完全图还可能吗?

所以总结一下

  • 若图中有非完全图,那么肯定不行
  • 若图中完全图数量大于2,也不行
  • 剩下的就行了

至于判断完全图,自己找规律,很多方法


Code
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define M 1005
#define LL long long

vector<int>G[M];
vector<int>c[M];

stack<int>ss;

int com_g_sum, uncom_g_sum;
int n, m, u, v, times, ans;
int Low[M], DFN[M], de[M];

bool vis[M], flag;

inline void dfs(int x){
    vis[x] = 1;
    int son;
    times++;
    Low[x] = DFN[x] = times;
    ss.push(x);
    int siz = G[x].size();
    for(int i = 0; i < siz; i ++){
        son = G[x][i];
        if( !DFN[son] ){
            dfs(son);
            Low[x] = min(Low[x], Low[son]);
        }
        else if( vis[son] )
            Low[x] = min(Low[x], DFN[son]);
    }
    if( Low[x] == DFN[x] ){
        ans ++;
        while(1){
            int t = ss.top();
            ss.pop();
            c[ans].push_back(t);
            if( t == x )
                break;
        }
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i ++ ){
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
        de[u] ++, de[v]++;
    }
    for(int i = 1; i <= n; i ++){
        if( !DFN[i] )
            dfs(i);
    }
    for(int i = 1; i <= ans; i ++){
        int siz = c[i].size();
        flag = 0;
        for(int j = 1; j < siz; j ++){
            int son = c[i][j];
            if( de[son] != de[c[i][j-1]] ){
                uncom_g_sum++;
                flag = 1;
                break;
            }
        }
        if( flag == 0 )
            com_g_sum++;
    }
    if( uncom_g_sum || com_g_sum > 2)
        printf("NE\n");
    else
        printf("DA\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值