蓝桥杯常用小技巧

  1. 将一个数的每一位取出
while(x)
{
	int t = x % 10;
	x /= 10;
}
  1. 将一个数字字符串转换为数字
int x = 0;
for(int i = 0; i < s.size(); i ++ )
{
	x = x * 10 + s[i] - '0';
}
  1. 判断日期是否合法
  2. 宽搜BFS的一般写法
    bfs能找到最短路径,dfs不能找最短路径
需要判重数组st[]、队列

queue<-初始状态
while(queue非空)
{
	取出队头t
	for(扩展t)
	{
        	ver<-新节点
		if(!st[ver])
		{
			queue<-ver // 入队尾
		}
	}
}
  1. BFS(DFS)算有多少个连通块
st[][]

for(int i = 0; i < n; i ++)
{
    for(int j = 0; j < n; j ++)
    {
        if(!st[i][j] && g[i][j] == '@')
        {
            bfs(i, j);
            cnt ++
        }
    }
}
  1. 求树的直径(树中两点的最大长度)
    思路:任意取一个点x,找到一个点y,距离x最远;再找距离y最远的点,这个最远的距离就是树的直径。(可以用反证法证明)
    上面这种方法树的边权一定要都为正数
  2. 图的存储方式
    邻接矩阵
    邻接表(每个节点都开一个单链表,存的是这个节点可以到的所有点)
// 邻接表的存储方式
// h存储的是头节点的值,e存储的是节点的值,ne存储下一个节点的值,w存储边的权值
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
// 遍历
for(int i = h[u]; ~i; i = ne[i])
{
	//
}
  1. 最大公约数
    gcd(a, b) = gcd(b, a % b)
    a mod b = a - (a / b) * b证明
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

数论知识:
质因数分解、线性筛质数、约数个数、约数之和、最大公约数、扩展欧几里得
筛法求1~n所有质数O(n)

void get_primes(int n)
{
    for(int i = 2; i <= n; i ++ )
    {
        if(!st[i])  primes[cnt ++] = i;
        for(int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0)  break;
        }
    }
}

扩展欧几里得算法:
gcd(a, b) = d, 求x、y使ax + by = d

int exgcd(int a, int b, int &x, int &y)
{
    if(!b)
    {
        x = 1, y = 0;
        return a;
    }
    int x1, y1;
    int d = exgcd(b, a % b, x1, y1);
    x = y1, y = x1 - (a / b) * y1;
}
  1. 最短路几个算法
    dijkstra算法: 有一个集合S是最小值确定的点,每次剩下的点中找出距离最小的点,将这个点加入集合S,用这个点来更新其他所有的点。(边权不能为负)O(n^2)
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 510, M = 100010, INF = 0x3f3f3f3f;
int dist[N], g[N][N];
bool st[N];
int n, m;

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    for(int i = 0; i < n; i ++ )
    {
        int t = -1;
        for(int j = 1; j <= n; j ++ )
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        st[t] = true;
        for(int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }
}

int main()
{
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    while (m -- )
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        if(x == y)  g[x][y] = 0;
        else    g[x][y] = min(g[x][y], z);
    }
    dijkstra();
    if(dist[n] == 0x3f3f3f3f)   puts("-1");
    else    printf("%d", dist[n]);
    
    return 0;
}

bellman-ford算法:有边数限制的最短路算法,用边来更新,dist[b] = min(dist[b], dist[a] + w[a][b]) O(nm)

#include <iostream>
#include <cstring>

using namespace std;

const int N = 510, M = 100010, INF = 0x3f3f3f3f;
int dist[N], backup[N];

struct edge
{
    int a, b, w;
}Edge[M];
int n, m, k;

void bellman_ford()
{
    memset(dist, 0x3f3f3f3f, sizeof dist);
    dist[1] = 0;
    for(int i = 0; i < k; i ++ )
    {
        memcpy(backup, dist, sizeof dist);
        for(int j = 0; j < m; j ++ )
        {
            int a = Edge[j].a, b = Edge[j].b, w = Edge[j].w;
            dist[b] = min(dist[b], backup[a] + w);
        }
    }
}

int main()
{
    cin >> n >> m >> k;
    for(int i = 0; i < m; i ++ )
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        Edge[i] = {x, y, z};
    }
    bellman_ford();
    if(dist[n] > INF / 2)   puts("impossible");
    else    printf("%d", dist[n]);
    
    return 0;
}

spfa算法:是对belllman_ford算法的优化,dist[b] = min(dist[b], dist[a] + w[a][b]),只有dist[a]变小了才用a更新b,用宽搜来优化,O(n)~O(nm)

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int N = 100010, INF = 0x3f3f3f3f;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];
int n, m;

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}

void spfa()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if(!st[j])
                {
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    while(m --)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z);
    }
    spfa();
    if(dist[n] > INF / 2)   puts("impossible");
    else    printf("%d", dist[n]);
    
    return 0;
}

floyd算法:多源最短路,基于动态规划f[i][j] = min(f[i][j], f[i][k] + f[k][j]),O(n^3)

#include <iostream>
#include <cstring>

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;
int f[N][N];

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    memset(f, 0x3f, sizeof f);
    for(int i = 1; i <= n; i ++ )   f[i][i] = 0;
    while (m -- )
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        f[x][y] = min(f[x][y], z);
    }
    
    for(int k = 1; k <= n; k ++ )
        for(int i = 1; i <= n; i ++ )
            for(int j = 1; j <= n; j ++ )
                f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
    
    while(k --)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        if(f[a][b] > INF / 2)   puts("impossible");
        else    printf("%d\n", f[a][b]);
    }
    
    return 0;
}
posted @ 2022-02-23 20:11  inss!w!  阅读(123)  评论(0编辑  收藏  举报