Codeforces Round #167 (Div. 1) C. Dima and Horses(BFS+贪心)

题目大意

有 n(1≤n≤3*105) 匹马,每条马都有几个敌人(不超过 3 个),现在要求把这些马分成两部分(允许一部分中没有一条马),使得对于每条马,和它在同一部分中的敌人的数量不超过1个

给出了所有的敌对关系,求一个划分的方案。如果不存在划分方案,输出-1

做法分析

首先,观察下为什么题目给的数据范围这么奇葩:

每条马的敌人的数量不超过 3 个

这有什么用呢?想了很久,画了好几个图,最终确定,这样的条件下,一定是存在一个划分方案,使得每部分中,每条马的敌人数量不超过 1 个。

可以考虑 4 个点的完全图,每个点的度是 3,对应了 3 个敌人,我们完全可以找出一种分配的方案使得这个图的点分成两个点集,那么,对于其余的情况,肯定也是能够找出一种解的,因为他们的关系比 4 个点的完全图的关系更加的简单

也就是说,输出 -1 的情况是不存在的

接下来就考虑怎么构造出一种分配的方案了

实在是想不出有什么其他的做法了,干脆贪心的找找,类似于 SPFA 的 BFS:

        ①. 先假设所有的马都在同一个部分中,把所有不合格的马(有超过 1 个敌人的)入队

        ②. BFS 的过程中,先把当前马移动到另一个部分中,然后再统计它的敌人中,哪些马变得不合法了,把不合法的加入到队列中

这样不断的 BFS,肯定能够找到一种分配方案,但是具体的时间复杂度不知道怎么计算的,迷迷糊糊的就过了......

参考代码

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <queue>
 5 
 6 using namespace std;
 7 
 8 const int N=300006;
 9 
10 int arc[N][10], n, m, ans[N];
11 queue <int> q;
12 
13 bool Ok(int u)
14 {
15     int cnt=0;
16     for(int i=1; i<=arc[u][0]; i++)
17     {
18         int v=arc[u][i];
19         if(ans[u]==ans[v]) cnt++;
20     }
21     return cnt<2;
22 }
23 
24 void BFS()
25 {
26     while(!q.empty()) q.pop();
27     for(int i=1; i<=n; i++)
28         if(!Ok(i)) q.push(i);
29     while(!q.empty())
30     {
31         int u=q.front();
32         q.pop();
33         if(Ok(u)) continue;
34         ans[u]^=1;
35         for(int i=1; i<=arc[u][0]; i++)
36             if(!Ok(arc[u][i])) q.push(arc[u][i]);
37     }
38 }
39 
40 int main()
41 {
42     scanf("%d%d", &n, &m);
43     for(int i=1; i<=n; i++) ans[i]=0, arc[i][0]=0;
44     for(int i=0, a, b; i<m; i++)
45     {
46         scanf("%d%d", &a, &b);
47         arc[a][++arc[a][0]]=b;
48         arc[b][++arc[b][0]]=a;
49     }
50     BFS();
51     for(int i=1; i<=n; i++) printf("%d", ans[i]);
52     printf("\n");
53     return 0;
54 }
C. Dima and Horses

题目链接 & AC通道

Codeforces Round #167 (Div. 1) C. Dima and Horses

原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3108783.html