靠二进制画几何[图论]
Posted kaike
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了靠二进制画几何[图论]相关的知识,希望对你有一定的参考价值。
@Kaike
今天来浅谈一下图,听说自己写总结的人grade++,rp++。
像我这样可爱的人怎么能错过这个机会呢嘤嘤嘤。
毕竟图至少啃了15day++。
恩曾经的小弱渣从来都是仰望高端玩家虐图论
听说noip上一年考两道大图(つд⊂)而小弱渣还没学到
吓得本宝宝虎躯一震!!
恩废话不多说,来开正文。
2019/01/27:
时隔两年重新看这篇博客,又更新的好多东西,希望自己一直能不断进步把,而不是一直啃以前的东西QAQ
-------------------我是萌哒哒的分割线--------------------
刚开始先学图的储存。
- 邻接矩阵
邻接矩阵就是跟二维数组长得一毛(mu)一样奇奇怪怪的东xi
1 #include<iostream>
2 using namespace std;
3 int n,a[100][100];
4 int main()
5 {
6 cin>>n;
7 //直接给出邻接矩阵,直接读。
8 for(int i=1;i<=n;i++)
9 for(int j=1;j<=n;j++)
10 cin>>a[i][j];
11 //给出两个顶点和权值
12 for(int i=1;i<=n;i++)
13 {
14 int xx,yy,vv;
15 cin>>xx>>yy>>vv;
16 a[xx][yy]=vv;
17 //双向图时
18 a[yy][xx]=vv;
19 }
20 //给出每个顶点的临界点
21 for(int i=1;i<=n;i++)
22 {
23 int k;
24 cin>>k;
25 for(int j=1;j<=k;j++)
26 {
27 int x;
28 cin>>x;
29 a[i][x]=1;
30 a[x][i]=1;
31 }
32 }
33 return 0;
34 }
2.邻接表
第一次看这玩意的时候内心万般草泥马奔过。
这TM都是什么玩意
后来经过滑稽大师cdc柴大叔的指导下,莫名其妙知道了些什么
然而教材太过简单,时常还会有些错的
小弱渣花了一整节自习课照着书上画了一幅图,发现!原来!跟书上一毛(mu)一样。本宝宝不开心,哦是十分不开心。
这大概是这个样子的
1 #include<iostream>
2 using namespace std;
3 int n;
4 int link[10010],len=0;
5 struct ha
6 {
7 int y,v,next;
8 }e[10010];
9 void insert(int xx,int yy,int vv)
10 {
11 e[++len].next=link[xx];
12 link[xx]=len;
13 e[len].y=yy;
14 e[len].v=vv;
15 }
16 int main()
17 {
18 cin>>n;
19 int xx,yy,vv;
20 for(int i=1;i<=n;i++)
21 {
22 cin>>xx>>yy>>vv;
23 insert(xx,yy,vv);
24 insert(yy,xx,vv);
25 }
26 return 0;
27 }
如果出现重边!邻接矩阵必须判断!!
-----------------我是萌萌哒的分割线------------------
DFS:以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问过。
1 #include<iostream> 2 using namespace std; 3 bool book[10010];//记录顶点是否被访问过 4 int a[10010][10010],n,m; 5 int inf=0x7fffffff; 6 int sum=0; 7 //邻接矩阵 8 void dfs(int x) 9 { 10 for(int i=1;i<=n;i++) 11 if(book[i]==0 && a[x][i]) 12 { 13 book[i]=1; 14 dfs(i); 15 } 16 } 17 //邻接表 18 void dfs(int x) 19 { 20 for(int i=link[x];i;i=e[i].next) 21 if(book[e[i].y]==0) 22 { 23 book[e[i].y]=1; 24 dfs(e[i].y); 25 } 26 } 27 int main() 28 { 29 cin>>n; 30 //初始化 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=n;j++) 33 if(i==j) a[i][j]=0; 34 else a[i][j]=inf; 35 int xx,yy,vv; 36 for(int i=1;i<=m;i++) 37 { 38 cin>>xx>>yy>>vv; 39 a[xx][yy]=vv; 40 a[yy][xx]=vv; 41 } 42 for(int i=1;i<=n;i++) 43 if(book[i]==0) 44 { 45 //求无向图的连接分量 46 sum++; 47 dfs(i); 48 } 49 return 0; 50 }
BFS:以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点,在访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过。
1 #include<iostream> 2 using namespace std; 3 bool book[10010];//记录顶点是否被访问过 4 int a[10010][10010],n,m; 5 int inf=0x7fffffff; 6 int sum=0; 7 int q[10010];//队列,数组一定要开大!! 8 //邻接矩阵 9 void bfs(int x) 10 { 11 int head=0,tail=1; 12 q[1]=x; 13 book[i]=1; 14 while(head<tail) 15 { 16 int k=q[++head]; 17 for(int i=1;i<=n;i++) 18 if(a[x][i] &&book[i]==0) 19 { 20 q[++tail]=i; 21 book[i]=1; 22 } 23 } 24 } 25 //邻接表 26 void dfs(int x) 27 { 28 int head=0,tail=1; 29 q[1]=x; 30 while(head<tail) 31 { 32 for(int i=link[q[head]];i;i=e[i].next) 33 if(book[e[i].y]==0) 34 { 35 book[e[i].y]=1; 36 q[++tail]=e[i].y; 37 } 38 } 39 } 40 int main() 41 { 42 cin>>n; 43 //初始化 44 for(int i=1;i<=n;i++) 45 for(int j=1;j<=n;j++) 46 if(i==j) a[i][j]=0; 47 else a[i][j]=inf; 48 int xx,yy,vv; 49 for(int i=1;i<=m;i++) 50 { 51 cin>>xx>>yy>>vv; 52 a[xx][yy]=vv; 53 a[yy][xx]=vv; 54 } 55 for(int i=1;i<=n;i++) 56 if(book[i]==0) 57 { 58 //求无向图的连接分量 59 sum++; 60 dfs(i); 61 } 62 return 0; 63 }
Bicoloring
这道题就是用bfs遍历一遍,用两种颜色来填充顶点,有边相邻的顶点颜色不能一样,邻接矩阵很好写,很好判断两个点,可是空间太大了。
邻接表想了好久,最终确定了两个顶点分别是 q[head] 和 e[i].y i=Link[q[head]]
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<algorithm> 8 #include<cmath> 9 using namespace std; 10 typedef long long ll; 11 const int N = 200 + 20; 12 int a[N][N]; 13 int cor[N]; 14 int n, m,flag=1,xx,yy; 15 void dfs(int x) 16 { 17 for (int i = 0; i < n; i++) 18 { 19 if (a[x][i] && cor[i] == 0) 20 { 21 if (cor[x] == 1) 22 cor[i] = 2; 23 else cor[i] = 1; 24 dfs(i); 25 } 26 else if (cor[i] == cor[x] &&a[x][i]) 27 { 28 flag = 0; 29 return; 30 } 31 } 32 } 33 int main() 34 { 35 while (scanf("%d", &n)) 36 { 37 if (n == 0) break; 38 memset(a, 0, sizeof(a)); 39 memset(cor, 0, sizeof(cor)); 40 flag = 1; 41 scanf("%d",&m); 42 while (m--) 43 { 44 scanf("%d %d",&xx,&yy); 45 a[xx][yy] = 1; 46 a[yy][xx] = 1; 47 } 48 cor[0] = 1; 49 dfs(0); 50 if (flag == 0) printf("NOT BICOLORABLE.\\n"); 51 else printf("BICOLORABLE.\\n"); 52 } 53 54 return 0; 55 }
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<vector> 8 #include<algorithm> 9 #include<cmath> 10 using namespace std; 11 typedef long long ll; 12 const int N = 100000 + 20; 13 int Link[N],cor[N],len=0,bok[N]; 14 int n, m; 15 int q[N]; 16 struct student 17 { 18 int y, next; 19 }e[N]; 20 void insert(int xx, int yy) 21 { 22 e[++len].next = Link[xx]; 23 Link[xx] = len; 24 e[len].y = yy; 25 } 26 int bfs(int x) 27 { 28 int head = 1, tail = 2; 29 q[1] = x; 30 bok[x] = 1; 31 cor[x] = 1; 32 while (head < tail) 33 { 34 for (int i = Link[q[head]]; i; i = e[i].next) 35 { 36 if (cor[e[i].y] == 0) 37 { 38 if (cor[q[head]] == 1) 39 cor[e[i].y] = 2; 40 else 41 cor[e[i].y] = 1; 42 } 43 else if (cor[e[i].y] == cor[q[head]]) 44 return 0; 45 if (bok[e[i].y] == 0) 46 { 47 bok[e[i].y] = 1; 48 q[tail++] = e[i].y; 49 } 50 } 51 head++; 52 } 53 return 1; 54 } 55 int main() 56 { 57 while (scanf("%d", &n)) 58 { 59 memset(bok, 0, sizeof(bok)); 60 memset(Link, 0, sizeof(Link)); 61 memset(q, 0, sizeof(q)); 62 memset(cor, 0, sizeof(cor)); 63 if (n == 0) break; 64 scanf("%d", &m); 65 while (m--) 66 { 67 int xx, yy; 68 scanf("%d %d", &xx, &yy); 69 insert(xx, yy); 70 insert(yy, xx); 71 } 72 if (bfs(0)) printf("BICOLORABLE.\\n"); 73 else printf("NOT BICOLORABLE.\\n"); 74 } 75 return 0; 76 }
拓扑排序:
拓扑就是类似于游戏中点技能,只有先把低级技能点了,才能点高阶技能。一个低阶技能可能对应多个高阶技能,高阶技能本身也可以互相对应。
那我们怎么办呢,另开一个数组indu,表示入度。
刚开始先找入度为0的点,从这个点开始遍历,然后再找,入度为1的点,再往下找入度为2的点。
每次找到一个,就减去它的入度,相当于把前面那个点删除掉,相应的边也删除掉。
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<vector> 8 #include<algorithm> 9 #include<cmath> 10 using namespace std; 11 typedef long long ll; 12 const int N = 10000; 13 int Link[110], bok[110],len=0,indu[110],que[N]; 14 int n, m, xx, yy; 15 struct student 16 { 17 int y, next; 18 }e[N]; 19 void insert(int xx, int yy) 20 { 21 e[++len].next = Link[xx]; 22 Link[xx] = len; 23 e[len].y = yy; 24 } 25 void bfs() 26 { 27 int head = 1, tail = 1; 28 for (int i = 1; i <= n; i++) 29 if (indu[i] == 0) 30 { 31 que[tail++] = i; 32 bok[i] = 1; 33 } 34 while (head < tail) 35 { 36 for (int i = Link[que[head]]; i; i = e[i].next) 37 { 38 if (--indu[e[i].y] == 0 && bok[e[i].y] == 0) 39 { 40 que[tail++] = e[i].y; 41 bok[e[i].y] = 1; 42 } 43 } 44 head++; 45 } 46 printf(洛谷P1027 Car的旅行路线 计算几何 图论最短路