图有关的一道题目
叶哥和圈姐正在一个含有 N 个顶点和 M 条边的简单连通图里玩游戏。
圈姐首先要将图中的每一条边染成红色或者蓝色。
一条路径是一系列边,其中每对连续边都有一个共同的节点。如果一对连续边中的第一条边的颜色与第二条边的颜色不同,我们就称这为“颜色变化”。
在圈姐的染色工作结束后,叶哥就需要选择一条起点为 1,终点为 N 的路径。
叶哥可以选择图中的任意一条路径,但是叶哥要使这条路径中的“颜色变化”的次数最少。而圈姐则是要让叶哥选择的路径中发生的“颜色变化”的次数最多,不管叶哥怎么选。
现在请你求出,不管叶哥怎么选,都必须发生颜色变化的次数。
输入格式:
第一行为两个整数,分别为 N 和 M,其中 2≤N≤105,1≤M≤105。
接下来的 M 行分别为两个整数 ai 和 bi,意思是 ai 和 bi 中有一条无向边,其中 1≤ai,bi≤N,ai\=bi
简单图 (Simple graph):若一个图中没有自环和重边,它被称为简单图。具有至少两个顶点的简单无向图中一定存在度相同的结点。
输出格式:
输出一个整数,即不管叶哥怎么选,都必须发生颜色变化的次数。
输入样例:
在这里给出一组输入。例如:
7 8
1 2
1 3
2 4
3 4
4 5
4 6
5 7
6 7
输出样例:
在这里给出相应的输出。例如:
3
解释:1-7这条路上,1-2颜色未变,从2->4,颜色由红色变为蓝色,颜色改变次数+1,接着从4到6,颜色由蓝色变为红色,颜色改变次数+1,再从6到7,颜色改变次数+1,总共颜色改变为3次;
刚开始看到题目是一脸懵逼的,仔细看后结果这么简单!!!先说结论,从1出发,找到一条最短路到n,求1-n中间经过的节点数就可以了。
从1~任意结点k 的颜色变换次数 等于 中间经过的节点数
为什么?叶哥想让颜色变换最少,那个女的又可以任意改变边的颜色;初始假设边的颜色都是蓝色并且两人足够聪明,叶哥无论怎么走,颜色变换都是0,现在女的给边染上红色(女的足够聪明),叶哥仍然要使颜色变换最少,即走最短路即可。假设不是走的最短路,由上面的结论可知中间的节点数肯定不是最少的,反之,即求最短路(我们这里使用堆优化dijkstra)。
广搜也可以,这里给你们用堆优化dijkstra是为了学习高级一点的东西,广搜有点太基础了。
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
//堆优化dijkstra:每次找最近的点的时候不是用数组存起来的,而是用一个堆来存,这样每次找最近的点
//都是O(1)的复杂度,调整堆是O(logn)的复杂度
using namespace std;
const int N = 1e5+5;
int n, m;
typedef struct Node {
int no, w;//no表示结点编号,w表示1-当前no的距离
//重载小于号,满足w >= b.w 的就排在堆的下面
bool operator < ( const Node &b ) const {
return w >= b.w;
}
}Vert;
//默认大根堆,我们要使用的是小根堆,所以上面重载了<
priority_queue<Vert> q;
//领接表
vector<int> chart[N];
int dis[N];
bool sign[N];
void dijkstra( int start )
{
dis[start] = 0;
Vert s = {start, 0};
q.push(s);
for ( int i = 1; i <= n; ++i )
{
if ( i != start ) {
dis[i] = 0x3f3f3f3f;
}
}
// for ( int i = 0; i < chart[start].size(); ++i ) {
// dis[chart[start][i]] = 1;
// }
// cout << "size:" << q.size() << endl;
while ( q.size() ) {
Vert first = q.top();
q.pop();
int no = first.no;
// cout << "no:" << no << endl;
if ( !sign[no] ) {
for ( int i = 0; i < chart[no].size(); ++i ) {
if ( !sign[chart[no][i]] && dis[chart[no][i]] > dis[no] + 1 ) {
dis[chart[no][i]] = dis[no] + 1;
Vert v = {chart[no][i], dis[chart[no][i]]};
q.push(v);
}
}
}
sign[no] = true;
}
}
int main()
{
cin >> n >> m;
for ( int i = 0; i < m; ++i ) {
int s, e;
cin >> s >> e;
chart[s].push_back(e);
chart[e].push_back(s);
}
dijkstra(1);
// for ( int i = 1; i <= n; ++i ) {
// cout << dis[i] << ' ';
// }
// cout << endl;
cout << dis[n]-1 << endl;
return 0;
}