[集训笔记2nd]图的入门
周六简单预习一下,真的是没怎么接触过,可能表现比上一周要差很多。
mmh大佬一脸嫌弃地教我图的遍历嘤嘤嘤。
图的遍历(洛谷P2661)
有 nnn 个同学(编号为 111 到nnn )正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 iii 的同学的信息传递对象是编号为 TiTiTi 的同学。
游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息, 但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自 己的生日时,游戏结束。请问该游戏一共可以进行几轮?
测试数据Input
5
2 4 2 3 1
Output
3
苦思冥想出来的做法,把所有入度为0的点(因为这些同学不可能收到信息)去掉,每去掉一个更新一次。
然后遍历所有环,经过的点就不遍历了,然后输出求最小环长。
一种比较方便点的做法是用并查集做,枚举n个点,把aiaiai和aiaiai指向的点pipipi做一次合并,然后再枚举i,如果遇到父节点是自己的就说明遇到了环(还不会重复遍历),然后用计步器走一遍环输出最小即可。
水题的代码给自己看,以后不会了再回来看QAQ。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; const int maxn = 5e5; int f[maxn], a[maxn]; int vis[maxn]; int cnt = 0; int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } int main() { int t, ans = 0x7fffffff; scanf("%d", &t); for (int i = 1; i <= t; i++) { scanf("%d", a + i), f[i] = i, vis[i] = 0; }; for (int i = 1; i <= t; i++) { int fi = find(i), fai = find(a[i]); if (fi != fai) { f[fi] = fai; } } for (int i = 1; i <= t; i++) { if (i == find(i)) { int j = i; int cnt = 1; while (a[j] != i) { j = a[j], cnt++; } ans = min(ans, cnt); } } printf("%d\n", ans); return 0; }
至少开始明白图是什么样子了。
拓扑排序
1.唯一的要点遍历入度为零的点并删掉。。
2.严格排序只能有一个入度为零的点
3.一定要找清楚偏序关系
4.拓扑排序可以用于有向图判环
有N个比赛队(1<=N<=500),编号依次为1,2,3,...N1,2,3,... N1,2,3,...N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
InputInputInput
4 3
1 2
2 3
4 3
OutputOutputOutput
1 2 4 3
ACACAC代码
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int maxn = 550; int defeat[maxn][maxn]; int n, m, pre[maxn]; int queue[maxn]; void topsort() { int i, j, top, k = 0; for (j = 0; j < n; j++) { for (i = 1; i <= n; i++) { if (pre[i] == 0) { top = i; break; } } queue[k++] = top; pre[top] = -1; for (int i = 1; i <= n; i++) { if (defeat[top][i]) { pre[i]--; } } } printf("%d", queue[0]); for (int i = 1; i < k; i++) { printf(" %d", queue[i]); } printf("\n"); } int main() { while (~scanf("%d%d", &n, &m)) { memset(defeat, 0, sizeof(defeat)< 4000 /span>); memset(pre, 0, sizeof(pre)); memset(queue, 0, sizeof(queue)); for (int i = 0; i < m; i++) { int a, b; scanf("%d%d", &a, &b); if (defeat[a][b] == 0) { defeat[a][b] = 1; pre[b]++; } } topsort(); } return 0; }加入了判环和严格偏序
给你nnn个点之间的关系,如A<B,B<CA<B, B<CA<B,B<C等,让你判断在m个关系内是否有一条严格的偏序关系
例如A<B<C<D<E<FA<B<C<D<E<FA<B<C<D<E<F
如果可以,就输出结果1
一定不可以,就输出到第几个关系就发现一定不可以的结果2
如果这些关系不够形成确定的关系(但也不是一定形不成,就是不确定),就输出结果3
多组输入到0 0 为止
InputInputInput
4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0
OutputOutputOutput
Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
ACACAC代码
#include <cstdio> #include <cstring> #include <iostream> #include <queue> using namespace std; const int maxn = 30; int n, m; int in[maxn]; int fin[maxn]; int po[maxn][maxn]; queue<char> q, result_q; string s; int topsort(string s, int N) { int flag = 0; int a = s[0] - 'A' ; int b = s[2] - 'A' ; if (po[a][b] == 0) { po[a][b] = 1; in[b]++; } for (int i = 0; i < n; i++) { fin[i] = in[i]; }; while (!q.empty()) { q.pop(); }; for (int i = 0; i < n; i++) { int top, cnt = 0; for (int j = 0; j < n; j++) { if (fin[j] == 0 4000 ) { top = j; cnt++; } } if (cnt == 0)return 1; else if (cnt > 1) flag = 1; q.push(top); fin[top]--; for (int j = 0; j < n; j++) { if (po[top][j]) { fin[j]--; } } } if (!flag) return 2; return 3; } int main() { while (1) { scanf("%d%d", &n, &m); if (n == 0 && m == 0) break; memset(in, 0, sizeof(in)); memset(po, 0, sizeof(po)); int flag = 0, ok = 1; for (int i = 0; i < m; i++) { cin >> s; if (ok) { flag = topsort(s, n); if (flag == 1) { printf("Inconsistency found after %d relations.\n", i+1); ok = 0; } else if (flag == 2) { printf("Sorted sequence determined after %d relations: ", i+1); while (!q.empty()) { printf("%c", 'A' + q.front()); q.pop(); } printf(".\n"); ok = 0; } } } if (ok) printf("Sorted sequence cannot be determined.\n"); } return 0; } //没想到找了4个小时的bug还拿到了训练的FB,调试bug真的酸爽 //思路一定要清晰不然图论题出bug会很惨
到现在学会了两种判断有向图中有无环的方法
1.topsort
2.并查集
- [集训笔记5th]树状数组与线段树的入门
- Android 开发笔记——环境入门
- [置顶] 【第三部分-django论坛从搭建到部署】一个完整的Django入门指南学习笔记
- Python小白入门学习笔记(一)
- Python笔记之入门(基础篇)
- Lua入门系列----pil学习笔记之Type and Values (2)
- 【php学习】PHP 入门经典第二章笔记
- 《Perl 语言入门》摘录笔记
- MyBatis笔记----MyBatis 入门经典的两个例子: XML 定义与注解定义
- JAVASE入门基础知识整理笔记篇一
- Oracle11g_入门笔记(一)
- unity3D-游戏/AR/VR在线就业班 蓝鸥C#入门泛型学习笔记
- Docker 入门笔记 10 - Control groups
- 学习笔记| AS入门(五) 高级控件篇(中)
- 黑马程序员—SQL入门笔记(下)
- Java入门笔记1_HelloWorld
- Java入门笔记3_Datastructure (转)
- C#入门笔记3 表达式及运算符
- 【GAN学习笔记】对抗式生成网络入门
- 《R语言入门与实践》学习笔记一