1154 Vertex Coloring (25 分) 适当顶点涂色 手绘样例图
A registration card number of PAT consists of 4 parts:the 1st letter represents the test level, namely, T for the top level, A for advance and B for basic;the 2nd - 4th digits are the test site num...
·
A proper vertex coloring is a labeling of the graph's vertices with colors such that no two vertices sharing the same edge have the same color. A coloring using at most k colors is called a (proper) k-coloring.
Now you are supposed to tell if a given coloring is a proper k-coloring.
Input Specification:
Each input file contains one test case. For each case, the first line gives two positive integers N and M (both no more than 10
4
), being the total numbers of vertices and edges, respectively. Then M lines follow, each describes an edge by giving the indices (from 0 to N−1) of the two ends of the edge.
After the graph, a positive integer K (≤ 100) is given, which is the number of colorings you are supposed to check. Then K lines follow, each contains N colors which are represented by non-negative integers in the range of int. The i-th color is the color of the i-th vertex.
Output Specification:
For each coloring, print in a line k-coloring if it is a proper k-coloring for some positive k, or No if not.
Sample Input:
10 11
8 7
6 8
4 5
8 4
8 1
1 2
1 4
9 8
9 1
1 0
2 4
4
0 1 0 1 4 1 0 1 3 0
0 1 0 1 4 1 0 1 0 0
8 1 0 1 4 1 0 5 3 0
1 2 3 4 5 6 7 8 8 9
Sample Output:
4-coloring
No
6-coloring
No
下面先附一个样例的手绘图,数字是定点编号,交点处为顶点,黑线为边。
这道题其实很简单,但我上去读错了题,我误以为是求每个邻边不同色的顶点的顶点-邻点点集颜色的最大种数,但其实根本没这么麻烦,它只是要判断这个图是否所有相邻顶点两两不同色,如果是,就输出总的颜色种数,如果否,就输出No。
那么只需要存下整个图,扫描每条边判断是否端点异色,同时存储颜色种数即可。我用了邻接表存储。
- 事实证明cin也比scanf慢,如果用cin,最慢用例用时800ms,其他都不改,仅仅把cin换成scanf,最慢用例就变成了250ms
#include<bits/stdc++.h>
#define N 10005
using namespace std;
vector<int> v[N];
int co[N];
int main() {
int n,m,k,a,b;
cin>>n>>m;
for (int i=0;i<m;i++) {
//cin>>a>>b;
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
cin>>k;
for (int i=0;i<k;i++) {
for (int j=0;j<n;j++) scanf("%d",&co[j]); //此处最初j误写了i,找了好久才发现
int cnt=-1;
set<int> si;
for (int p=0;p<n;p++) { //对所有邻接表
si.insert(co[p]);
for (int y=0;y<(int)v[p].size();y++) {
if (co[v[p][y]]==co[p]) {cnt=0;break;}
si.insert(co[v[p][y]]);
}
if (cnt==0) break;
}
if (cnt==0) printf("No\n");
else printf("%d-coloring\n",(int)si.size());
}
return 0;
}
复杂度分析:主要时间消耗在对整个邻接表的遍历上。设顶点n个,边m条,外层双循环总时间复杂度为n,内层set底层是map,map底层是红黑树,查找插入删除都是O(logn),则总复杂度约为O(nlogm)(不一定对,因为这是一个双层循环,并且在不同处有两个插入)。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)