您的位置:首页 > 其它

[集训笔记2nd]图的入门

2019-07-28 19:34 100 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_43279710/article/details/97529170

周六简单预习一下,真的是没怎么接触过,可能表现比上一周要差很多。
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&lt;B,B&lt;CA&lt;B, B&lt;CA<B,B<C等,让你判断在m个关系内是否有一条严格的偏序关系
例如A&lt;B&lt;C&lt;D&lt;E&lt;FA&lt;B&lt;C&lt;D&lt;E&lt;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.并查集
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: