Note:
本文旨在后期自己复习方便所纪录。部分代码不保证可运行行,有问题欢迎指出。
#include
#include
typedef char ElemType;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode, *LinkList;
// 下面是带头节点的链表
bool InitList(LinkList& L){
if(!(L = (LinkNode* )malloc(sizeof(LinkNode)))) { // 没创建成功
printf("it is not enough space.\n");
return false;
}
L->next = NULL;
return true;
}
bool DestroyList(LinkList& L){
free(L);
}
bool ClearList(LinkList& L){
L->next = NULL;
}
bool ListEmpty(LinkList L){
return (L->next == NULL) ? true : false;
}
int ListLength(LinkList L){
int length = 0;
LinkNode *p = L->next;
while(p){
length++; p = p->next;
}
return length;
}
bool GetElem(LinkList L, int i, ElemType &e){
if(i < 1 || i > ListLength(L)) return false;
int cnt = 1;
LinkNode *p = L->next;
while(p){
if(cnt == i) {
e = p->data;
return true;
}
p = p->next;
cnt++;
}
}
bool Compare(ElemType a, ElemType b){
if(a == b) return 0;
if(a > b) return 1;
else return -1;
}
// 传参 函数指针 确定比较方式
int LocateElem(LinkList L, ElemType e, bool (*Compare)(ElemType, ElemType)){
LinkNode *p = L->next;
int pos = 1;
while(p){
if(!Compare(p->data, e))
return pos;
++pos;
p = p->next;
}
return 0; // 0 表示没找到
}
bool ListInsert(LinkList& L, int i, ElemType e){
if(i < 1 || i > ListLength(L) + 1) return false;
LinkNode *p = L->next, *fa = L;
LinkNode *cur = (LinkNode *) malloc(sizeof(LinkNode));
cur->data = e; cur->next = NULL;
int pos = 1;
while(p){
if(pos == i) break;
++pos;
p = p->next; fa = p->next;
}
fa->next = cur;
cur->next = p;
}
bool LinkDelete(LinkList &L, int i){
if(i < 1 || i > ListLength(L)) return false;
LinkNode *p = L->next, *fa = L;
int pos = 1;
while(p){
if(pos == i){
fa->next = p->next;
return true;
}
++pos;
p = p->next;
fa = fa->next;
}
}
bool LinkTraverse(LinkList L){
L = L->next;
while(L){
printf("%c ", L->data);
L = L->next;
}
puts(""); // 换行
}
// test ..
int main(){
LinkList L;
InitList(L);
ElemType tmp = 'a';
ListInsert(L, 1, 'a');
LinkTraverse(L);
tmp = 'c';
ListInsert(L, 1, tmp);
LinkTraverse(L);
LinkDelete(L, 2);
LinkTraverse(L);
return 0;
}
#include
#include
typedef char ElemType;
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LISTINCRMENT 10 // 线性表存储空间的分配增量
typedef enum {OK, OVERFLOW, ERROR} Status;
typedef struct{
ElemType *elem;
int length; //当前线性表长度
int listsize; // 当前分配的存储容量
}SqList;
Status InitList_Sq(SqList &L){
L.elem = (ElemType *) malloc(sizeof(ElemType) * LIST_INIT_SIZE);
if(!L.elem) return OVERFLOW;
L.listsize = LIST_INIT_SIZE;
L.length = 0;
return OK;
}
Status ListInsert_Sq(SqList &L,int i, ElemType e){
if(i < 1 || i > L.length + 1) return ERROR;
if(L.length >= L.listsize) { // 容量满了,扩孔容量
ElemType *base = (ElemType *) realloc(L.elem, (L.listsize + LISTINCRMENT) * sizeof(ElemType));
if(!base) exit(OVERFLOW);
L.elem = base;
L.listsize += LISTINCRMENT;
}
ElemType *q = &(L.elem[i - 1]);
for(ElemType *p = &(L.elem[L.length - 1]); p >= q; p--)
*(p + 1) = *p;
*q = e;
++L.length;
return OK;
}
Status ListDelete_Sq(SqList &L, int i){
if(i < 1 || i > L.length) return ERROR;
ElemType *p, *q;
q = &(L.elem[L.length - 1]);
for(p = &(L.elem[i - 1]); p < q; ++p)
*p = *(p + 1);
--L.length;
return OK;
}
void Traverse(SqList L){
for(int i = 0; i < L.length; i++){
printf("%c ", L.elem[i]);
}
puts("");
}
int main(){
SqList L;
InitList_Sq(L);
ElemType e = 'a';
ListInsert_Sq(L, 1, e);
e = 'c';
ListInsert_Sq(L, 1, e);
Traverse(L);
ListDelete_Sq(L, 2);
Traverse(L);
return 0;
}
#include
#include
typedef enum{OK, ERROR, OVERFLOW}Status;
#define STACK_INIT_SIZE 100 // 栈的初始容量
#define STACKINCREMENT 10 // 每次扩充的容量
typedef char ElemType;
typedef struct{
ElemType *base;
ElemType *top;
int stacksize;
}SeqStack;
Status InitStack(SeqStack &S){
S.base = (ElemType *)malloc(sizeof(ElemType) * STACK_INIT_SIZE);
if(!S.base) exit(OVERFLOW );
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status GetTop(SeqStack S, ElemType &e){
if(S.top == S.base) return ERROR;
e = *(S.top - 1);
return OK;
}
Status Push(SeqStack &S, ElemType e){
if(S.top - S.base >= S.stacksize) {// 栈满 扩充栈
ElemType *base = (ElemType*) realloc(S.base,
(S.stacksize + STACKINCREMENT) * (ElemType));
if(!base) exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return OK;
}
bool StackEmpty(SeqStack S){
return S.top == S.base;
}
void StackClear(SeqStack &S){
S.top = S.base;
}
Status Pop(SeqStack &S, ElemType &e){
if(S.top == S.base) return ERROR;
e = *--S.top;
return OK;
}
// TEST
int main(){
SeqStack S;
InitStack(S);
ElemType c = 'c';
Push(S, c);
Push(S, c);
c = 'a';
Push(S, c);
while(!StackEmpty(S)) {
ElemType t;
GetTop(S, t);
printf("%c ", t);
Pop(S, t);
}
return 0;
}
#include
#include
typedef char ElemType;
typedef struct QNode{
ElemType data;
struct QNode *next;
}QNode, *QueuePtr;
typedef struct {
QueuePtr front, rear;
}LinkQueue;
typedef enum{OK, ERROR, OVERFLOW} Status;
Status InitQueue(LinkQueue &Q){
Q.front = Q.rear = (QNode*) malloc (sizeof(QNode));
if(!Q.front)exit(OVERFLOW);
return OK;
}
bool QueueEmpty(LinkQueue Q){
return Q.front == Q.rear;
}
Status DestroyQueue(LinkQueue &Q){
ElemType *p;
while(!QueueEmpty(Q)){
}
}
Status EnQueue(LinkQueue &Q, ElemType e){
QNode *p = (QNode*) malloc(sizeof(QNode));
if(!p) exit(OVERFLOW);
p->data = e; p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return OK;
}
Status DeQueue(LinkQueue &Q, ElemType &e){
if(Q.front == Q.rear) return ERROR;
QNode *p;
p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if(p == Q.rear) Q.rear = Q.front;
free(p);
return OK;
}
Status GetHead(LinkQueue Q, ElemType &e){
if(Q.front == Q.rear) return ERROR;
e = Q.front->next->data;
return OK;
}
int main(){
return 0;
}
#include
#include
typedef char ElemType;
typedef enum{OK, ERROR, OVERFLOW} Status;
#define MAXQSIZE 1000
typedef struct {
ElemType *que;
int front, rear;
} SeqQueue; // 通过浪费一个存储单元 来区分满还是空
Status InitQueue(SeqQueue &Q){
Q.que = (ElemType*) malloc (sizeof(ElemType) * MAXQSIZE);
Q.front = Q.rear = 0;
}
Status ClearQueue(SeqQueue &Q){
Q.front = Q.front = 0;
}
bool QueueEmpty(SeqQueue Q){
return Q.front == Q.rear;
}
Status EnQueue(SeqQueue& Q, ElemType e){
if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;
Q.que[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return OK;
}
Status DeQueue(SeqQueue&Q, ElemType &e){
if(Q.rear == Q.front) return ERROR;
e = Q.que[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return OK;
}
int QueueLength(SeqQueue Q){
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
int main(){
return 0;
}
#include
#include
typedef char ElemType;
typedef enum{OK, ERROR, OVERFLOW} Status;
#define MAXQSIZE 1000
typedef struct {
ElemType *que;
int front, rear;
bool flag; // 通过flag来区分满还是空
} SeqQueue;
/*
if front == rear
if flag == 1 空
if flag == 0 满
*/
Status InitQueue(SeqQueue &Q){
Q.que = (ElemType*) malloc (sizeof(ElemType) * MAXQSIZE);
Q.front = Q.rear = 0;
Q.flag = 1;
}
Status ClearQueue(SeqQueue &Q){
Q.front = Q.front = 0;
Q.flag = 1;
}
bool QueueEmpty(SeqQueue Q){
return (Q.front == Q.rear) && Q.flag;
}
Status EnQueue(SeqQueue& Q, ElemType e){
if((Q.front == Q.rear) && !Q.flag) return ERROR;
Q.que[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
Q.flag = 0;
return OK;
}
Status DeQueue(SeqQueue&Q, ElemType &e){
if((Q.rear == Q.front) && Q.flag) return ERROR;
e = Q.que[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
Q.flag = 1;
return OK;
}
int QueueLength(SeqQueue Q){
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
int main(){
return 0;
}
#include
#include
bool BF(char *s, char *t){
int i, j, k;
i = 0, j = 0;
int lens = strlen(s), lent = strlen(t);
while(i < lens){
while(i < lens && j < lent && s[i] == t[j]) ++i, ++j;
if(j >= lent) return true;
j = 0; i = i - j + 1;
}
}
const int N = 1000; // 模式串的最长长度
int next[N];
void getnext(char *s, int len){
next[0] = -1;
int i, j;
i = 0; j = -1;
while(i < len){
if(j == -1 || s[i] == s[j] )
next[++i] = ++j;
else
j = next[j];
}
}
bool Kmp(char *s, char *t){
int lens = strlen(s), lent = strlen(t);
getnext(t, lent);
int i, j;
i = j = 0;
while(i < lens){
if(j == -1 || s[i] == t[j]) {
++i, ++j;
if(j >= lent) return true;
}
else
j = next[j];
}
}
int main(){
return 0;
}
#include
#include
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef ElemType SqBiTree[MAX_TREE_SIZE];
// 适合存完全二叉树或者满二叉树
// 举个例子: 给完全二叉树上的两个节点的序号,求其最近公共祖先(LCA)
ElemType solve(SqBiTree T, int a, int b){
while(a != b){
if(a > b) b /= 2;
else a /= 2;
}
return T[a];
}
int main(){
return 0;
}
#include
#include
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef struct BNode{
ElemType data;
struct BNode *lchild;
struct BNode *rchild;
}BNode, *BiTree;
void Inorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
// visit(T->data);
printf("%c ", T->data);
Inorder(T->rchild);
}
void preorder(BiTree T){
if(T == NULL) return ;
// visit(T->data);
printf("%c ", T->data);
Inorder(T->lchild);
Inorder(T->rchild);
}
void postorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
Inorder(T->rchild);
// visit(T->data);
printf("%c ", T->data);
}
#define MAX 200
void leverorder(BiTree T){
BiTree queue[MAX];
int front , rear;
front = rear = 0;
queue[rear++] = T;
while(front < rear){
BiTree p = queue[front++];
printf("%c ", p->data);
if(p->lchild) queue[rear++] = p->lchild;
if(p->rchild) queue[rear++] = p->rchild;
}
}
int main(){
return 0;
}
#include
#include
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef struct BNode{
ElemType data;
struct BNode *lchild;
struct BNode *rchild;
}BNode, *BiTree;
void Inorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
// visit(T->data);
printf("%c ", T->data);
Inorder(T->rchild);
}
void preorder(BiTree T){
if(T == NULL) return ;
// visit(T->data);
printf("%c ", T->data);
Inorder(T->lchild);
Inorder(T->rchild);
}
void postorder(BiTree T){
if(T == NULL) return ;
Inorder(T->lchild);
Inorder(T->rchild);
// visit(T->data);
printf("%c ", T->data);
}
#define MAX 200
void leverorder(BiTree T){
BiTree queue[MAX];
int front , rear;
front = rear = 0;
queue[rear++] = T;
while(front < rear){
BiTree p = queue[front++];
printf("%c ", p->data);
if(p->lchild) queue[rear++] = p->lchild;
if(p->rchild) queue[rear++] = p->rchild;
}
}
int main(){
return 0;
}
#include
#include
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef struct BNode{
ElemType data;
struct BNode *lchild;
struct BNode *rchild;
}BNode, *BiTree;
void inorder(BiTree T){
InitStack(S);
BNode *p = T;
while(!StackEmpty(S) || p){
if(!p) {
Push(S, p);
p = p->lchild;
}else {
Pop(S, p);
printf("%c ", p->data);
p = p->rchild;
}
}
}
void postorder(BiTree T){
InitStack(S);
BNode *p = T, *last = NULL;
while(!StackEmpty(S) || p){
if(p){
Push(S, p);
p = p->lchild;
}
else {
GetTop(S, p);
if(p->rchild && p == last){ // 向右子树 递归
Pop(S, p);
printf("%c ", p->data);
last = p;
p = NULL;
}else {
p = p->rchild;
}
}
}
}
int main(){
return 0;
}
#include
#include
#define MAX_TREE_SIZE 100
typedef char ElemType;
typedef struct BNode{
ElemType data;
bool ltag, rtag;
struct BNode *lchild;
struct BNode *rchild;
}BNode, *BiTree;
void DFS(BiTree T, BiTree &pre){
if(T == NULL) return ;
T->ltag = T->rtag = 0;
DFS(T->lchild, pre);
if(!T->lchild) {
T->ltag = 1;
T->lchild = pre;
}
if(!pre->rchild) {
pre->rtag = 1;
pre->rchild = T;
}
pre = T;
DFS(T->rchild, pre);
}
// 构造 中序线索化二叉树
void BinaryTree_Thread_Inorder(BiTree T){
BiTree pre = NULL;
DFS(T, pre);
pre->rtag = 0;
pre->rchild = NULL;
}
BiTree First(BiTree T){
while(!T->ltag) {
T = T->lchild;
}
return T;
}
BiTree Next(BiTree T){
if(T->rtag) return T->rchild;
else
First(T->rchild);
}
// 遍历线索化二叉树
void Traverse_Inorder_Thread(BiTree T){
BiTree p;
for(p = First(T); p; p = Next(p)) {
printf("%c ", p->data);
}
}
int main(){
return 0;
}
#include
#include
#include
const int N = 1e5 + 11;
int pre[N];
void Init(int n){ // n 为集合大小
for(int i = 1; i <= n; i++){
pre[i] = i; // 每个集合用自己表示自己
}
}
int Find(int x) { // 寻找元素x属于哪个集合
while(pre[x] != x) {
x = pre[x];
}
return x;
}
void Join(int x,int y){ // 将x 和 y 集合合并
int fx = Find(x);
int fy = Find(y);
if(fx != fy){
pre[fx] = fy;
}
}
// 此为简单 幷查集,幷查集还可以考虑带权幷查集,不过考研用不到。
// 还可以考虑 启发式合并(比如说 结点少的向结点多的合并),防止退化成链
int Find_(int x ) { // 带有路径压缩的 查找
return (pre[x] == x) ? x : pre[x] = Find(pre[x]);
}
int main(){
return 0;
}
#include
#include
#define InfoType char
#define VertexType char // 顶点信息
#define MAX_VERTEX_NUM 100 // 最大顶点数量
typedef struct ArcNode{
int adjvex; // 邻接顶点
struct ArcNode *next;
InfoType *info; // 该弧相关信息的指针
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 当前顶点数量和弧的数量
int kind; // 图的种类标识
}ALGraph;
int main(){
ALGraph G;
int n, m; scanf("%d%d", &n, &m);
ArcNode *arc;
while(m--){ // 建图
int a, b, c;
scanf("%d%d%d", &a, &b, &c); // a --> b 的weight为c的无向边
arc = (ArcNode *) malloc(sizeof(ArcNode));
arc->next = G.vertices[a].firstarc; // 头插法
G.vertices[a].firstarc = arc;
arc = (ArcNode *) malloc(sizeof(ArcNode));
arc->next = G.vertices[b].firstarc; // 头插法
G.vertices[b].firstarc = arc;
}
int u = 1; // 遍历 所有和u相邻的顶点v
for(arc = G.vertices[u].firstarc; arc; arc = arc->next){
int v = arc->adjvex;
}
return 0;
}
#include
#include
#include
/*
十字链表 用来存储有向图
其实就是将邻接表和逆邻接表合并一起
*/
#define MAX_VERTEX_NUM 100 // 最多的顶点数
typedef char InfoType;
typedef int ElemType;
typedef struct ArcNode{
int tailvex, headvex; // tailvex -> headvex 的一条边
struct ArcNode *tlink, *hlink; // 分别为弧尾和弧头相同的弧的链域
InfoType *info; // 存储 弧上信息
}ArcNode;
typedef struct VexNode{
ElemType data; // 顶点信息
ArcNode *firstin, *firstout; // 第一个指向当前顶点和第一个当前顶点指向的弧链
}VexNode;
typedef struct {
VexNode xlist[MAX_VERTEX_NUM];
int vexnum, arcnum;
}OLGraph;
int main(){
OLGraph olg;
int n, m; scanf("%d%d", &n, &m);
olg.arcnum = m; olg.vexnum = n;
for(int i = 0; i <= olg.vexnum; i++){
olg.xlist[i].firstin = olg.xlist[i].firstout = NULL;
}
for(int i = 0; i < m; i++){
int a, b; // a->b 的有向弧
scanf("%d%d%d", &a, &b, &c);
ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
*p = {a, b, olg.xlist[a].firstout, olg.xlist[b].firstin, NULL}; // 都采用头插入法
//{tailvex, headvex, tlink, hlink, info}
olg.xlist[a].firstout = olg.xlist[b].firstin = p;
}
return 0;
}
#include
#include
/*
邻接多重表 用来存无向图
*/
typedef char ElemType;
#define MAX_VEX_NUM 10000
typedef struct ArcNode{
int ivex, jvex;
struct ArcNode *ilink, *jlink;
// 可以再保存一个 弧上的信息
}ArcNode;
typedef struct VNode{
ElemType data; // 顶点信息
ArcNode *firstout;
}VNode;
typedef struct {
VNode adjmulist[MAX_VEX_NUM];
int vexnum, arcnum;
}AMLGraph;
int main(){
AMLGraph G;
int n, m; scanf("%d%d", &n, &m);
G.vexnum = n; G.arcnum = m;
for(int i = 0; i <= G.vexnum; i++){ // 清空
G.adjmulist[i].firstout = NULL;
}
while(m--){
int a, b; // a->b的一个无向弧
scanf("%d%d", &a, &b);
ArcNode *p = (ArcNode *) malloc (sizeof(ArcNode));
*p = {a, b, G.adjmulist[a].firstout, G.adjmulist[b].firstout};
G.adjmulist[a].firstout = G.adjmulist[b].firstout = p;
}
int u; // 遍历所有 和u相邻的顶点v
for(ArcNode *p = G.adjmulist[u].firstout; p; p = p->ilink) {
int v = p->jvex;
}
return 0;
}
#include
#include
#include
/*
生成DFS序列
存储图用的是邻接表
*/
#define InfoType char
#define VertexType char // 顶点信息
#define MAX_VERTEX_NUM 100 // 最大顶点数量
typedef struct ArcNode{
int adjvex; // 邻接顶点
struct ArcNode *next;
InfoType *info; // 该弧相关信息的指针
}ArcNode;
typedef struct VNode{
VertexType data;
ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 当前顶点数量和弧的数量
int kind; // 图的种类标识
}ALGraph;
bool vis[MAX_VERTEX_NUM];
void DFS(ALGraph G, int u){
printf("%d ", u);
vis[u] = true;
for(ArcNode *p = G.vertices[u].firstarc; p; p = p->next){
int v = p->adjvex;
if(!vis[v]){
DFS(G, v);
}
}
}
int main(){
ALGraph G;
int n, m; scanf("%d%d", &n, &m);
for(int i = 0; i <= n; i++){
G.vertices[i].firstarc = NULL; // 清空
}
ArcNode *arc;
while(m--){ // 建图
int a, b, c;
scanf("%d%d%d", &a, &b, &c); // a --> b 的weight为c的无向边
arc = (ArcNode *) malloc(sizeof(ArcNode));
*arc = {b, G.vertices[a].firstarc, NULL};
G.vertices[a].firstarc = arc;
arc = (ArcNode *) malloc(sizeof(ArcNode));
*arc = {a, G.vertices[b].firstarc, NULL};
G.vertices[b].firstarc = arc;
}
// 得到DFS序列
memset(vis, false, sizeof(vis)); //清空 标记
for(int i = 1; i <= n; i++){
if(!vis[i]) // 有可能图不是连通的,所以这样遍历 将所有顶点都访问到
DFS(G, i);
}
return 0;
}
/*
input_sample :
5 3
1 2 0
1 3 0
4 5 1
*/
/*
topo 排序过程中可以
1. 判断有向图是否有环
2. 判断出topo序列是否唯一
*/
void Topo(G, in){ // 图G和顶点的入度in
int cnt = 0; // 记录访问了几个顶点
bool flag = true; // topo是否唯一
Init(que);
int cur = 0;
for(int i = 0; i < G.vexcnt; i++){
if(!in[i]) {
print(i); // 输出顶点
cnt++;
cur ++;
Enqueue(que, i);
}
}
if(cur > 1) flag = 0;
while(!IsEmpty(que)){
Dequeue(que, v);
cur = 0;
for(w = FirstEdge(G, v); w; w = NextEdge(G, v, w)) {
if(--in[w] == 0) {
print(w); // 输出顶点
cnt++;
cur ++;
Enqueue(que, w);
}
}
if(cur > 1) flag = 0;
}
if(cnt < G.vexcnt) puts("有向图中有环!"); // 有环的话 不会遍历所有的顶点
else if(!flag) puts("topo序不唯一"); // 每次 只有一个入度为0的 ,这样topo序才唯一
else puts("topo序唯一");
}
#include
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;
vector<int>G[N];
int dfn[N], low[N], clo;
int bcc_cnt, st[N], iscut[N], bccno[N];
void tarjan(int u, int fa){
dfn[u] = low[u] = ++clo; st[++*st] = u;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(!dfn[v] && v != fa){
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
++bcc_cnt;
iscut[u] = true;
do{
bccno[st[*st]] = bcc_cnt;
}while(st[st[0]--] != u);
st[++*st] = u; // 割点会属于多个bcc ,所以要再填充进去
}
}else
low[u] = min(low[u], dfn[v]);
}
if(fa == -1 && G[u].size() < 2) iscut[u] = false;
}
void bcc_cut(int n){
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(iscut, false, sizeof(iscut));
memset(bccno, 0, sizeof(bccno));
st[0] = bcc_cnt = clo = 0;
for(int i = 1; i <= n; i++)
if(!dfn[i])
tarjan(i, -1);
}
int main(int argc, char **args){
int n, m; scanf("%d%d", &n, &m);
while(m--){
int a, b; scanf("%d%d",&a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
bcc_cut(n);
for(int i = 1;i <= n;i ++){
printf("%d %d %d\n", i, iscut[i], bccno[i]);
}
return 0;
}
/*
7 8
1 2
1 3
1 4
1 6
1 7
4 5
3 5
6 7
*/
#include
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;
vector<int>G[N];
int dfn[N], low[N], clo;
int ebc_cnt, ebcno[N];
int st[N];
void tarjan(int u,int fa){
low[u] = dfn[u] = ++clo; st[++*st] = u;
for(int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(!dfn[v] && v != fa){
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u]){
// 当前边是桥
}
}else
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == dfn[u]){
++ebc_cnt;
do{
ebcno[st[*st]] = ebc_cnt;
}while(st[st[0]--] != u);
}
}
void ebc(vector<int> G, int n ){
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
clo = ebc_cnt = 0;
memset(ebcno, 0, sizeof(ebcno));
for(int i = 1; i <= n; i++){
if(!dfn[i])
tarjan(i, -1);
}
}
int main(int argc, char **args){
return 0;
}
#include
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 11;
const int M = 1e6 + 11;
const int MOD = 1e9 + 7;
vector<int>ve[N];
bool instack[N];
int st[N];
int scc_cnt, sccno[N];
int clo, low[N], dfn[N];
void tarjan(int u){
low[u] = dfn[u] = ++clo; st[++*st] = u; instack[u] = 1;
for(int i = 0; i < ve[u].size(); i++){
int v = ve[u][i];
if(!dfn[v]){
tarjan(v);
if(low[u] > low[v]) low[u] = low[v];
}else if(instack[v]) {
if(low[u] > dfn[v]) low[u] = dfn[v];
}
}
if(dfn[u] == low[u]) { // 发现一个scc
scc_cnt++;
do{
sccno[st[*st]] = scc_cnt;
}while(st[st[0]--] != u);
}
}
void scc_cut(int n){
memset(instack, false, sizeof(bool) * (n + 1));
memset(dfn, 0, sizeof(int) * (n + 1));
memset(low, 0, sizeof(int) * (n + 1));
memset(sccno, 0, sizeof(int) * (n + 1));
st[0] = clo = scc_cnt = 0;
for(int i = 1; i <= n; i++){
if(!dfn[i])
tarjan(i);
}
}
int main(int argc, char **args){
return 0;
}
#include
using namespace std;
struct Edge {
int from,to,val;
}edge[MAXN];
bool cmp(Edge a,Edge b){
return a.val<b.val;
}
int par[MAXN];
int n,m,k;
int Find(int x){ // 查找 x点所属的集合 ( 同时进行路径压缩)
return x==par[x] ? x : par[x]=Find(par[x]);
}
void join(int a,int b){
a=Find(a);
b=Find(b);
if(a!=b) par[a]=b;
}
void krus(){
int sum=0;
sort(edge,edge+m,cmp); // 排序
for(int i=0;i<m;i++){
Edge e=edge[i];
if(Find(e.from)!=Find(e.to)) { // 如果该边的两个点分别属于各自连通块,那么这两个连通块就要进行连通,该边就要用上。
sum+=e.val;
join(e.from,e.to); // 连接 两个连通块
}
}
printf("%d\n",sum); // 最小花费
}
int main(){
scanf("%d%d%d",&n,&m); // n 个点,m个边
int a,b,c;
for(int i=0;i<m;i++)
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].val);
// 初始化 并查集
for(int i=0;i<=n;i++)
par[i]=i;
krus();
return 0;
}
dijkstra
#include
#include
#define INF 0x3f3f3f
#define max 100+10
int dist[max],map[max][max],pre[max],visit[max];
int n,m;
void dijkstra()
{
int i,j,start=1;
int next;
int mindist;//找最小的距离
memset(visit,0,sizeof(visit));//初始化
for(i=1;i<=n;i++)
{
dist[i]=map[start][i];
}
visit[1]=1;
for(i=2;i<=n;i++)
{
mindist=INF;
for(j=1;j<=n;j++)
{
if(visit[j]==0&&mindist>dist[j])
{
mindist=dist[j];
next=j;
}
}
visit[next]=1;
for(j=1;j<=n;j++)
{
if(visit[j]==0&&dist[next]+map[next][j]<dist[j])
{
dist[j]=dist[next]+map[next][j];
}
}
}
printf("%d\n",dist[n]);
}
int main()
{
int i,j;
int x,y,c;
while(scanf("%d%d",&n,&m)&&(n!=0||m!=0))
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
map[i][j]=0;//这里很重要
else
map[i][j]=INF;
}
}
while(m--)
{
scanf("%d%d%d",&x,&y,&c);
if(map[x][y]>c)//建议养成习惯加上可能会有重边的的情况
{
map[x][y]=map[y][x]=c;
}
}
dijkstra();
}
return 0;
}
int binary_search(int A[], int n, int key){ // 0 ~ n-1
int low, high, mid;
low = 0, high = n - 1;
while(low <= high){
mid = (low + high) / 2;
if(A[mid] == key) return mid;
else if(A[mid] > key) high = mid - 1;
else low = mid + 1;
}
return -1; // 没查到
}
int Index(String S,String T, int pos){ // A中pos后第一个与T匹配
int i = pos, j = 1;
while(i <= S.length && j <= T.length){
if(S.ch[i] == T.ch[j]) {
++i; ++j;
}else {
i = i - j + 2; j = 1;
}
}
if(j > T.length) return i - T.length;
else return 0;
}
void getnxt(char *s, int *nxt){
int i, j;
j = nxt[0] = -1;
i = 0; int n = strlen(s);
while(i < n){
while(j != -1 && s[i] != s[j]) j = nxt[j];
++j; ++i;
if(s[j] == s[i]) nxt[i] = nxt[j];
else nxt[i] = j;
}
}
int kmp(char *s, char *t){
int n = strlen(s), m = strlen(t);
getnxt(t, next);
int i = 0, j = -1;
while(i < n){
if(j == -1 || s[i] == t[j]) {
++i; ++j;
if(j == m - 1) return i - m + 1; // 找到t串
}else
j = next[j];
}
return -1;
}
#include
#include
/*
散列表的拉链法
散列表 其实常用来 处理对应问题(eg:c++中的map, python中的字典)
*/
typedef int ElemType;
#define MAX_KEYS 11000 // 最大的 关键字值
typedef struct ArcNode{
ElemType value;
int key;
struct ArcNode * next;
}ArcNode;
ArcNode *HashTable[MAX_KEYS];
bool search(int key, ElemType &values){
ArcNode *p = HashTable[key % MAX_KEYS];
while(p) {
if(p->key == key) break;
p = p->next;
}
if(p) values = p->value;
return p != NULL;
}
bool Insert(int key, ElemType values){
ElemType e;
if(search(key, e)) return false; // 已经有了,不用插入
ArcNode *p = (ArcNode*) malloc (sizeof(ArcNode));
*p = {values, key, HashTable[key % MAX_KEYS]};
HashTable[key % MAX_KEYS] = p;
}
// 删除 对于拉链法来说,和链表的删除操作一样(不带头节点的 链表删除,还是稍微有些繁琐)
bool Del(int key){
ElemType e;
if(!search(key, e)) return false; // 没有插入,删除失败
ArcNode *p = HashTable[key % MAX_KEYS];
if(p->key == key) HashTable[key % MAX_KEYS] = p->next; // 第一个结点就是要删除的结点,特判
else{ // 其他情况 ,处理起来都一样(如果是带头节点的 链表,就不用特判了
ArcNode *fa = p; p = p->next;
while(p && p->key != key) {
p = p->next;
fa = fa->next;
}
fa->next = p->next;
}
return true;
}
int main(){
for(int i = 0; i < MAX_KEYS;i++) HashTable[i] = NULL;
int op; scanf("%d", &op); // 操作的次数
while(op--){
int kind;
scanf("%d", &kind);
if(kind == 1) { // 插入 操作
int key;
ElemType value = 21;
// scanf("%d %1s", &key, &value);
scanf("%d %d", &key, &value);
// printf("insert : %d %c\n", key, value);
Insert(key, value);
}else if(kind == 2){// 删除操作
int key; scanf("%d", &key);
Del(key);
}else {
int key; scanf("%d", &key);
ElemType value;
if(search(key, value))
printf("%d\n", value);
}
}
return 0;
}
/*
6
1 2 1111
1 3 22222
3 2
1111
3 3
22222
2 2
3 2
*/
#include
#include
/*
BST (二叉搜索树)
二叉树形态 会由于插入而导致 退化为链,从而导致
时间复杂度暴增,所以针对这个问题,后面又提出了AVL,始终保持
二叉树高度(保持二叉树高度,有很多方法,红黑树、伸展树、平衡树等等
,目的都是为了保持二叉树的高度)
*/
typedef char ElemType;
typedef struct BNode{
ElemType data;
BNode *lchild, *rchild;
}BNode, *BSTree;
BSTree Insert(BSTree T, ElemType e){
if(!T) {
T = (BNode*) malloc (sizeof(BNode));
*T = {e, NULL, NULL};
return T;
}
if(e < T->data)
T->lchild = Insert(T->lchild, e);
else if(e >T->data)
T->rchild = Insert(T->rchild, e);
else {
//插入失败
}
}
bool reseach(BSTree T, ElemType e){
if(!T) return false;
if(e <T->data )
return reseach(T->lchild, e );
else if(e >T->data)
return reseach(T->rchild, e);
else
return true;
}
BSTree Delete(BSTree T, ElemType e){
if(!T){
// 没有 可删除元素
return NULL;
}
if(e < T->data)
T->lchild = Delete(T->lchild, e);
else if(e > T->data)
T->rchild = Delete(T->rchild, e);
else {
if(!T->lchild && !T->rchild) // 叶子结点
return NULL;
else if(!T->lchild) // 只有右孩子
return T->rchild;
else if(!T->rchild) // 只有左孩子
return T->lchild;
else { // 左右孩子都有
BNode*p = T->lchild; // 找前驱
while(p->rchild) p = p->rchild;
T->data = p->data; // 把值复制过来,继续递归左子树
return Delete(T->lchild, e); // 问题转化为 前两种情况
}
}
}
int main(){
return 0;
}
#include
#include
#include
#include
using namespace std;
typedef int ElemType;
typedef struct BNode{
ElemType data;
struct BNode *lchild, *rchild;
}BNode, *AVLTree;
int getH(BNode *root){
if(root == NULL) return 0;
return max(getH(root->lchild), getH(root->rchild)) + 1;
}
BNode *RR(BNode *root){
BNode * t = root->rchild;
root->rchild = t->lchild;
t->lchild = root;
return t;
}
BNode *LL(BNode *root){
BNode *t = root->lchild;
root->lchild = t->rchild;
t->rchild = root;
return t;
}
BNode *LR(BNode *root){
root->lchild = RR(root->lchild);
return LL(root);
}
BNode *RL(BNode *root){
root->rchild = LL(root->rchild);
return RR(root);
}
BNode *Insert(BNode *root,ElemType e){
if(root == NULL){
root = (BNode*) malloc(sizeof(BNode));
root->lchild = root->rchild = NULL;
root->data = e;
}else if(e < root->data){
root->lchild = Insert(root->lchild, e);
if((getH(root->lchild) - getH(root->rchild) )== 2) {
if(e < root->lchild->data)
root = LL(root);
else
root = LR(root);
}
}else {
root->rchild = Insert(root->rchild, e);
if((getH(root->rchild) - getH(root->lchild) )== 2){
if(e < root->rchild->data)
root = RL(root);
else
root = RR(root);
}
}
return root;
}
bool Search(AVLTree T, ElemType e){
if(T == NULL) return false;
if(e < T->data)
return Search(T->lchild, e);
else if(e >T->data) Search(T->rchild, e);
else
return true;
}
BNode *Delte(AVLTree T, ElemType e){
if(T == NULL){
exit(0);
}
if(e < T->data){
T->lchild = Delte(T->lchild, e);
if(getH(T->rchild) - getH(T->lchild) == 2) {
BNode *t = T->rchild;
if(getH(t->rchild) >= getH(t->lchild))
T = RR(T);
else
T = RL(T);
}
}else if(e > T->data){
T->rchild = Delte(T->rchild, e);
if(getH(T->lchild) - getH(T->rchild) == 2){
BNode *t = T->lchild;
if(getH(t->lchild) >= getH(t->rchild))
T = LL(T);
else
T = LR(T);
}
}else {
if(T->lchild == NULL && T->rchild == NULL){
free(T);
return NULL;
}else if(T->lchild == NULL) {
free(T);
return T->rchild;
}else if(T->rchild == NULL) {
free(T);
return T->lchild;
}else {
BNode *p = T->lchild;
while(p->rchild) p = p->rchild; // 找到前驱
swap(T->data,p->data); // 交换与前驱的值,递归删除左子树,这样就转化为前面三种情况了
T->lchild = Delte(T->lchild, e);
}
}
return T;
}
int main(){
AVLTree avl = NULL;
int n; scanf("%d", &n);
int t;
for(int i = 0; i < n; i++){
scanf("%d", &t);
avl = Insert(avl, t);
}
printf("%d\n", avl->data);
int q ; scanf("%d", &q);
while(q--){
scanf("%d", &t);
avl = Delte(avl, t);
printf("%d\n", avl->data);
}
return 0;
}
/*
5
5 4 3 2 1
4
4 1 2 3
*/
#include
#include
#include
/*
键树(字典树)
*/
#define MAX 26
typedef struct TNode{
char ch; // 存的字符
bool end; // 是否为一个单词的结尾
int count; // 有多少个字符串经过这个结点
TNode *son[MAX]; // 下属的 MAX个 指针
}TNode, *Trie;
bool research(Trie T, char *s){
int pos = 0; int len = strlen(s);
TNode * p = T;
while(p && pos < len)
p = p->son[s[pos++] - 'a'];
return pos == len;
}
void IninNode(Trie &T){
T = (Trie) malloc(sizeof(TNode));
for(int i = 0; i < MAX; i++){
T->son[i] = NULL;
}
T->count = 0;
T->end = false;
}
void Insert(Trie &T, char *s){
if(!T){ // 字典树根节点
IninNode(T);
T->count = 1;
}
Trie p = T; int pos = 0; int len = strlen(s);
while(p && pos < len){
p = p->son[s[pos++] - 'a'];
if(!p){ // 新建一个结点
IninNode(p);
}
p->count++;
}
p->end = true;
}
bool Del(Trie T, char *s){
if(!research(T, s)) return false;
int pos = 0; int len = strlen(s);
TNode * p = T, *q;
while(p && pos < len) {
if(!p->count) q = p;
p = p->son[s[pos++] - 'a'];
p->count --;
free(q);
}
return pos == len;
}
int main(){
return 0;
}
void InsertSort(int A[], int n){ // 1 ~ n
for(int i = 2; i <= n; i++){
if(A[i] < A[i - 1])
A[0] = A[i]; // 设置标兵 这样最后一定会中断。
for(int j = i - 1; A[j] > A[0]; j--){
A[j + 1] = A[j];
A[j + 1] = A[0];
}
}
}
void Insert(int A[], int n ){
int i, j, low, high, mid;
for(int i = 2; i <= n; i++){
A[0] = A[i];
low = 1, high = i - 1;
while(low <= high){
mid = (low + high) / 2;
if(A[mid] > A[0]) high = mid - 1;
else
low = mid + 1;
}
// 二分upper_bound 找到位置 (high + 1)
for(int j = i - 1; j >= high + 1; j--) // 移位
A[j + 1] = A[j];
A[high + 1] = A[0];
}
}
void shellSort(int A[], int n){
int i, j, gap;
for(gap = n / 2; gap > 0; gap /= 2){ // 增量
for(i = gap + 1; i <= n; i++){
A[0] = A[i];
for(j = i - gap; j > 0 && A[j] > A[0]; j -= gap) // 对同一组的 进行简单插入排序
A[j + gap] = A[j];
}
A[j + gap] = A[0];
}
}
void BubbleSort(int A[], int n){
bool flag;
for(int i = 1; i <= n; i++){
flag = false;
for(int j = n - 1; j >= i; j--){ // 不断交换
if(A[j] > A[j + 1]) {
swap(A[j], A[j + 1]);
flag = true;
}
}
if(!flag) break;
}
}
void qsort(int A[], int low, int high){
if(low < high){
int pivot = A[low]; // 中间值
while(low < high){
while(low < high && A[high] > pivot) high--;
A[low] = A[high];
while(low < high && A[low] <= pivot) low++;
A[high] = A[low];
}
A[low] = pivot;
qsort(A, low, low - 1); // 继续递归
qsort(A, low + 1, high);
}
}
/*
第i趟选择i~(n-1)中最小值交换
*/
void SelectSort(int A[], int n){ // 0 - (n-1)
for(int i = 0; i < n; i++){
int mn = i;
for(int j = i + 1; j < n; j++){
if(A[mn] > A[j])
mn = j;
}
if(mn != i) swap(A[i], A[mn]);
}
}
/*
构造 大根堆
利用完全二叉树的性质
*/
void BuildMaxHeap(int A[], int len){ // 1 - n
for(int i = len / 2; i > 0; i--) // 从最后一个结点的父节点开始,不断调整
AdjustDown(A, i, len);
}
void AdjustDown(int A[], int fa, int len){
A[0] = A[fa];
for(int i = fa * 2; i <= len; i *= 2){
if(i < len && A[i] < A[i + 1])
i++; // 取key较大的子节点 下标
if(A[0] >= A[i]) break; // 位置找到
else {
A[fa] = A[i]; // 调整位置
fa = i;
}
}
A[fa] = A[0];
}
void HeapSort(int A[], int len){
BuildMaxHeap(A, len);
for(int i = len; i > 1; i--){ // 每次根 是最大值,与A[i]交换后,重新调整即可。
swap(A[i], A[1]);
AdjustDown(A, 1, i - 1);
}
}
void Delete(int A[], int &len){ // 注意 len 的 &,因为删除后长度要变.
swap(A[1], A[len]); // 与最后一个元素交换
len--;
AdjustDown(A, 1, len); // 重新调整
}
void insert(int A[],int k){ // A[k] 中存着 新插入的值
A[0] = A[k];
for(int p = k / 2; p > 0 && A[p] < A[0];){ // p 为 k 节点的父节点,
A[k] = A[i]; // 不断向上 调整
k = i;
p = k / 2;
}
A[k] = A[0];
}
int *B = (int *) malloc(sizeof(int) * (n + 1)); // 辅助数组
void Merge(int A[], int low, int mid, int high){
/*
A[low ~ mid] 和 A[mid+1 ~ high] 合并为一个有序的序列
*/
for(int i = low; i <= high; i++)
B[i] = A[i];
int i, j, k;
for(i = low, j = mid + 1, k = low; i <= mid && j <= high; k++){
if(B[i] < B[j])
A[k] = B[i++];
else
A[k] = B[j++];
}
while(i <= mid) A[k++] = A[i++];
while(j <= mid) A[k++] = A[j++];
}
void MergeSort(int A[], int low, int high){
if(low < high){
int mid = (low + high) / 2;
MergeSort(A, low, mid);
MergeSort(A, mid + 1, high);
Merge(A, low, mid, high);
}
}