靠二进制画几何[图论]

Posted kaike

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了靠二进制画几何[图论]相关的知识,希望对你有一定的参考价值。

@Kaike

今天来浅谈一下图,听说自己写总结的人grade++,rp++。

像我这样可爱的人怎么能错过这个机会呢嘤嘤嘤。

毕竟图至少啃了15day++。

恩曾经的小弱渣从来都是仰望高端玩家虐图论

听说noip上一年考两道大图(つд⊂)而小弱渣还没学到

吓得本宝宝虎躯一震!!

恩废话不多说,来开正文。

 

2019/01/27:

时隔两年重新看这篇博客,又更新的好多东西,希望自己一直能不断进步把,而不是一直啃以前的东西QAQ

-------------------我是萌哒哒的分割线--------------------

刚开始先学图的储存。

 

  1. 邻接矩阵

邻接矩阵就是跟二维数组长得一毛(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 }
dfs

 

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 }
bfs

 

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的旅行路线  计算几何  图论最短路

Nyoj 一笔画问题(图论)

为啥这个 CSS 片段可以画一个三角形? [复制]

用几何画板画垂线的方法

如何用几何画板画60度角

几何画板怎样画半圆