题解,git的使用,MySQL与JDBC的使用(上)

题解

引入:tarjan算法,强连通分量,割点,割边,点双联通分量,边双联通分量

 P4961 小埋与扫雷
思路:分别求出数字和空格相加即可

#include<iostream>
using namespace std;
const int X[8] = { -1,-1,-1,0,0,1,1,1 };
const int Y[8] = { -1,0,1,-1,1,-1,0,1 };
int dir[8][2]{ {-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1} };
int a[1005][1005];
int n, m, ans;
void dfs(int x, int y){
    a[x][y] = 3;
    for (int i = 0; i < 8; i++) {
        int tx = x + dir[i][0];
         int ty = y + dir[i][1];
         if (tx >= 1 && tx <= n && ty >= 1 && ty <= m) {
             if (!a[tx][ty])
                 dfs(tx, ty);
         }
    }
}
int main()
{
    cin >> n >> m; 
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            if (!a[i][j])
                for (int l = 0; l < 8; l++) {
                    int tx = i + dir[l][0];
                    int ty = j + dir[l][1];
                    if (a[tx][ty] == 1)
                        a[i][j] = 2;
                }
        }
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            if (a[i][j] == 2)  {
                int flag = 1;
                for (int l = 0; l < 8; l++){
                    if (a[i + X[l]][j + Y[l]] == 0 && i + X[l] >= 1 && i + X[l] <= n && j + Y[l] >= 1 && j + Y[l] <= m)
                        flag = 0;
                }
             ans+=flag;
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++){
            if (!a[i][j]){
                ans++;
                dfs(i, j);
            }
        }
    }
    cout << ans;
    return 0;
}


洛谷P3388 【模板】割点(割顶)
给出一个 n 个点,m 条边的无向图,求图的割点。
如果 p 存在一个子结点 q 满足 low(q)≥dfsn(p) ,则p为割点
 特殊情况,根节点需要有两个子节点才为割点

#include<iostream>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
const int MAXN = 1000000;
int dfsn[MAXN], low[MAXN];
vector<int>edges[MAXN];
bool cut[MAXN];
int sum = 0 , cnt;
void tarjan(int p, bool root = true)
{
    int tot = 0;
    low[p] = dfsn[p] = ++cnt;
    for (auto q : edges[p])
    {
        if (!dfsn[q])
        {
            tarjan(q, false);
            low[p] = min(low[p], low[q]);
            tot += (low[q] >= dfsn[p]); // 统计满足low[q] >= dfsn[p]的子节点数目
        }
        else
            low[p] = min(low[p], dfsn[q]);
    }
    if (tot > root) { // 如果是根,tot需要大于1;否则只需大于0
        sum++;
        cut[p] = true;
    } 
}
int main()
{
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }
    for (int i = 1; i <= n; ++i)
           if (!dfsn[i])
           tarjan(i);
    cout << sum << '\n';
    for (int i = 1; i <= n; i++) {
        if (cut[i])
            cout << i << ' ';
    }
    return 0;
} 
洛谷P3387 【模板

】缩点
思路:tarjan求出强连通分量,缩点建新图,之后拓扑序dp

#include<iostream>
#include<stack>
#include<algorithm>
#include<vector>
#include<queue>
#define int long long
const int MAXN = 1e5+10;
using namespace std;
vector<int> edges[MAXN];
vector<int> edges2[MAXN];
stack<int>stk;
int dfsn[MAXN], low[MAXN], instk[MAXN], scc[MAXN], cnt, cscc;
int   ans;
int a[MAXN],w[MAXN],dis[MAXN];
int d[MAXN];
void tarjan(int p)
{
    low[p] = dfsn[p] = ++cnt;
    instk[p] = 1;
    stk.push(p); // 进栈
    for (auto q : edges[p])
    {
        if (!dfsn[q]) // 未访问过
        {
            tarjan(q); // 递归地搜索
            low[p] = min(low[p], low[q]);
        }
        else if (instk[q]) // 访问过,且q可达p
            low[p] = min(low[p], dfsn[q]);
    }
    if (low[p] == dfsn[p]) // 发现强连通分量的根
    {
        int top;
        cscc++;
        do
        {
            top = stk.top();
            stk.pop();
            instk[top] = 0;
            scc[top] = cscc; // 记录所属的强连通分量
        } while (top != p); // 直到弹出p才停止
    }
}
signed main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= m; i++) {
        int a, b;
        cin >> a >> b;
        edges[a].push_back(b);
    }
    for (int i = 1; i <= n; ++i)
        if (!dfsn[i])
            tarjan(i);
    for (int u = 1; u <= n; ++u) {     //缩点
        for (auto v : edges[u]) {
            if (scc[u] != scc[v]) {
                edges2[scc[u]].push_back(scc[v]);
                d[scc[v]]++;
            }
        }
        w[scc[u]] += a[u];         //记录值包括(强连通分量)
    }
    queue<int>q;
    for (int i = 1; i <= cscc; i++) {
        if (d[i] == 0) {                 //选择入度为0的点
            dis[i] = w[i];
            q.push(i);
        }
    }
    while (q.size()) {            //直到入度为0的点不存在
        int u = q.front();
        q.pop();
        for (auto v : edges2[u]) {
            dis[v] = max(dis[v], dis[u] + w[v]);
            d[v]--;                  //删除与之相连的所有边,即入度-1
            if (d[v] == 0) {
                q.push(v);
            }
        }
    }
    for (int i = 1; i <= cnt; i++) {         //比较以i为终点的最大值
        ans = max(ans, dis[i]);
    }
    cout << ans << '\n';
    return 0;
}
P1656 炸铁路


割桥模板题
如果 p 是 q 的父节点,并且low(q)>dfsn(p) ,那么 p<->q 是桥。

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 5e3+10;
vector<int> bridges;
int dfsn[MAXN], low[MAXN], fa[MAXN], cnt;
vector<int>edges[MAXN];
int sum = 0,ans;
struct edge {
    int u, v;
}e[MAXN];
bool cmp(edge x, edge y) {
    if (x.u == y.u)
        return x.v < y.v;
    return x.u <y.u;
}
void tarjan(int p)
{
    low[p] = dfsn[p] = ++cnt;
    for (auto to : edges[p])
    {
        if (!dfsn[to])
        {
            fa[to] = p; // 记录父节点
            tarjan(to);
            low[p] = min(low[p], low[to]);
            if (low[to] > dfsn[p]) {
                e[ans].u = min(to,p);
                e[ans].v = max(to, p);
                ans++;
            }
        }
        else if (fa[p] != to) // 排除父节点
            low[p] = min(low[p], dfsn[to]);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }
    for (int i = 1; i <= n; ++i)
        if (!dfsn[i])
            tarjan(i);
    sort(e, e + ans, cmp);
    for (int i = 0; i < ans; i++) {
        cout << e[i].u << ' ' << e[i].v << '\n';
    }
    return 0;
}


P2863[USACO06JAN]The Cow Prom S
 tarjan算法求出强连通分量,统计强连通分量>1的即可

#include<iostream>
#include<stack>
#include<algorithm>
#include<vector>
const int MAXN = 5e4+10;
using namespace std;
vector<int> edges[MAXN];
vector<int> edges2[MAXN];
stack<int>stk;
int dfsn[MAXN], low[MAXN], instk[MAXN], scc[MAXN], cnt, cscc;
int ans;
bool vis[MAXN];
int Cnt[MAXN];
void tarjan(int p)
{
    low[p] = dfsn[p] = ++cnt;
    instk[p] = 1;
    stk.push(p); // 进栈
    for (auto q : edges[p])
    {
        if (!dfsn[q]) // 未访问过
        {
            tarjan(q); // 递归地搜索
            low[p] = min(low[p], low[q]);
        }
        else if (instk[q]) // 访问过,且q可达p
            low[p] = min(low[p], dfsn[q]);
    }
    if (low[p] == dfsn[p]) // 发现强连通分量的根
    {
        int top;
        cscc++;
        do
        {
            top = stk.top();
            stk.pop();
            instk[top] = 0;
            scc[top] = cscc; // 记录所属的强连通分量
        } while (top != p); // 直到弹出p才停止
    }
}
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int a, b;
        cin >> a >> b;
        edges[a].push_back(b);
    }
    for (int i = 1; i <= n; ++i)
        if (!dfsn[i])
            tarjan(i);
    for (int i = 1; i <= n; i++) {
        Cnt[scc[i]]++;
        if (Cnt[scc[i]] > 1 && !vis[scc[i]]) {
            ans++;
            vis[scc[i]] = 1;
        }
    }
    cout << ans << '\n';
    return 0;
}


P8435 【模板】点双连通分量
思路:寻找割点,特判根节点,根节点需要有两个子节点才为割点,弹栈直到割点为点,点双连通分量

#include <iostream>
#include<vector>
using namespace std;
const int maxn = 5e6 + 10;
int n, m, cut[maxn];
struct edge {
    int to, nxt;
    edge() {};
    edge(int tto, int nnxt) {
        to = tto;
        nxt = nnxt;
    }
}d[maxn]; int head[maxn], cnt = 1;
void add(int u, int v) {          //链式前向星
    d[++cnt] = edge(v, head[u]);
    head[u] = cnt;
}
int low[maxn], dfn[maxn], stac[maxn], top, id, dc;
vector<int>dcc[maxn];
void tarjan(int u, int root)
{
    dfn[u] = low[u] = ++id, stac[++top] = u;
    if (u == root && !head[u])//孤立点
    {
        dcc[++dc].push_back(u);
        return;
    }
    for (int i = head[u]; i; i = d[i].nxt)
    {
        int v = d[i].to;
        if (!dfn[v])            // 未访问过
        {
            tarjan(v, root);       // 递归地搜索
            low[u] = min(low[u], low[v]);
            if (low[v] >= dfn[u])//不通过u,v无法回到更浅的节点,割点
            {
                int temp; ++dc;//开始弹栈 
                //注意,如果u是父节点且只有1个儿子,不算割点,但也会开始弹栈 
                while (temp = stac[top--])
                {
                    dcc[dc].push_back(temp);
                    if (temp == v)    break;//直到遇到v 
                }
                dcc[dc].push_back(u);
            }
        }
        else    
            low[u] = min(low[u], dfn[v]);
    }
}
int  main()
{
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int l, r; cin >> l >> r;
        if (l == r)
            continue;
        add(l, r); add(r, l);
    }
    for (int i = 1; i <= n; i++)
        if (!dfn[i])    tarjan(i, i);
    cout << dc << '\n';
    for (int i = 1; i <= dc; i++)
    {
        cout << dcc[i].size() << ' ';
        for (int j = 0; j < dcc[i].size(); j++)
            cout << dcc[i][j] << " ";
        cout << '\n';
    }
}


P8436 【模板】边双连通分量
 思路:边联通分量即没有桥的连通分量,两个不同强连通分量不可达,
 转变成求强连通分量
 

#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 5e5+10, M = (2e6+10) * 2;
int n, m;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
int id[N], dcc_cnt;
int tot[N];
vector<int>dcc[M];
void add(int a, int b){
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}
void tarjan(int u, int from){
    dfn[u] = low[u] = ++timestamp;
    stk[++top] = u;
    for (int i = h[u]; ~i; i = ne[i]){
        int j = e[i];
        if (!dfn[j]){
            tarjan(j, i);
            low[u] = min(low[u], low[j]);
        }
        else if (i != (1 ^ from))
            low[u] = min(low[u], dfn[j]);
    }
    if (dfn[u] == low[u])
    {
        dcc_cnt++;
        int y;
        do
        {
            y = stk[top--];
            dcc[dcc_cnt].push_back(y);
        } while (y != u);
    }
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
        add(b, a);
    }

    for (int i = 1; i <= n; i++)
        if (!dfn[i]) tarjan(i, -1);

    cout << dcc_cnt << endl;
    for (int i = 1; i <= dcc_cnt; i++)
    {
        cout << dcc[i].size() << ' ';
        for (int j = 0; j < dcc[i].size(); j++)
            cout << dcc[i][j] << " ";
        cout << '\n';
    }
    return 0;
}

git的使用()
版本迭代,版本管理器
1.版本控制
版本控制是指在软件开发过程中对各种程序代码、配置文件及说明文档等文件变更的管理,版本控制系统能够随着时间的推进记录一系列文件的变化,方便以后随时回退到某个版本。
多人开发
分类:
本地版本控制系统:个人
集中式版本控制系统 svn:协同工作的人们通过客户端连到中央服务器,需要联网,从服务器上拉取最新的代码,在本地开发,开发完成再提交到中央服务器。
分布式版本控制系统git:每个人拥有全部代码,安全隐患,不会因为服务器或网络造成不能工作


2.启动git
右键选项,任意文件夹
Git Bash:Unix与Linux风格的命令行
Git CMD:Windows风格命令行
Git GUI:图形界面的Git


3.常见的linux命令

更多
gitee下的git大全和git命令学习
蓝色目录,绿色程序,白色程序
注:切勿rm -rf/                 (格式化)

 

4.git的配置
查看配置    git config -l
查看系统配置   git config --system --list
查看本地配置    git config --global --list
注:用户名与密码必须配置
git的相关配置文件
所有的配置文件其实都保存在本地
D:\Git\Git\etc\gitconfig        系统级--system
C:\Users\abcd\.gitconflag    只适用当前登陆用户配置--global
设置用户与密码
git config --global user.name"用户"


5.git的工作原理(核心)
环境变量只是为了全局使用
Workspace:工作区  平时代码存放
Index/Stage:暂存区       临时存放改动,本质文件
Repository:仓库区   安全存放代码的地方    有提交的所有版本信息
Remote:远程仓库   托管代码的服务器


6.git工作的基本流程
1.工作目录添加,修改文件
2.需要进行版本管理的文件放入暂存区域
3.将暂存区域文件提交到git仓库


7.git的项目搭建


创建本地仓库(初始化)
git init  创建全新的仓库
git clone    克隆全新的仓库
git的文件操作
文件的4种状态 Untracked ,Unmodify ,Modified ,staged

 


git add .             添加所有文件到暂存区
git commit -m”消息内容“         提交暂存区的东西到本地仓库 -m为提交信息
忽略文件

 
8.使用码云
登陆注册
设置本机绑定SSH公匙,实现免密登陆
ssh-keygen -t rsa
生成公匙 在C:\Users\abcd\.ssh\id_rsa.pub复制粘贴即可
使用码云建立自己的仓库


9.IDEA中集成Git操作
新建项目,绑定git:将远程的git文件目录拷贝到项目中即可
注:红色为选中状态,绿色为提交
修改文件,使用idea操作git
git add .和git commit -m”消息内容“  和git push即可
提交测试

10.git的分支


多个分支并行执行,导致代码不冲突,同时存在多个版本
master主分支应非常稳定,一般不允许在上面工作,工作一般在新建的dev分支工作,工作完要发布或dev非常稳定可以合并在主分支 

 MySQL与JDBC的使用(上)

前端(页面;展示,)
后台(连接点,连接数据库JDBC,连接前端(控制,控制视图跳转,和给前端传递数据))
数据库(存数据,txt,Excel,word)
一.
1.数据库的分类
关系型数据库(SQL):MySQL,Oracle 表与表之间,行与列之间的关系数据存储
非关系型数据库(NOSQL): Redis,MongDB  对象存储,通过对象属性决定
DBMS(数据库管理系统)

2.SQLyog的下载

3.操作
每一个sqlyog的执行操作,本质上对应了一个sql,
创建数据库
新建一张表
查看表:尝试添加多条记录

4.基本的命令行操作
http://t.csdn.cn/TM7Op
DDL   定义
DML   操作
DQL   查询
DCL   控制

二.操作数据库
http://t.csdn.cn/H8OHA(了解即可)
创建数据库,删除数据库,使用数据库,查询数据库
注:将用可视化操作名创建的使用show后复制粘贴即可变成sql语句
例子:show create database 名 查看创建数据库的语句
show create 名       查看数据表的定义语句
desc 名       显示表的结构

1.数据库的列类型
https://learn.microsoft.com/zh-cn/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-ver16
重要 int  varchar   text    datatime    timestamp
注意:不要使用NULL进行运算,结果为NULL

2.数据库的字段属性(重点)
https://zhuanlan.zhihu.com/p/136958310
unsigned     无符号
zerofill     0填充
自增             自动在上一条语句+1(默认)设置唯一主键index,必须为整数类型,可以自定义起始值与步长
非空
默认

3.MYISAM与InnoDB的区别


设置数据库表的字符集编码,不设置为mysql默认字符集编码,不支持中文

4.修改和删除数据表字段

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 什么是Git?它有什么优点? Git是一款版本控制系统,它可以记录代码的历史变化,便于多人协作开发和管理代码。它的优点包括: - 分布式管理:每个开发者都可以拥有一份完整的代码仓库,不需要依赖中央服务器。 - 强大的分支和合并功能:可以轻松地创建和合并分支,便于团队协作和版本管理。 - 快速轻便:Git采用了一些高效的算法和数据结构,使得它的速度非常快。 - 安全性高:Git使用SHA-1算法来保证代码的完整性和安全性。 2. Git的三个区域分别是什么? Git的三个区域分别是工作区、暂存区和版本库。 - 工作区:保存了实际的文件,也就是我们编辑的文件。 - 暂存区:保存了即将提交到版本库的文件,也就是我们通过`git add`命令添加的文件。 - 版本库:保存了所有的提交历史和代码版本,也就是我们通过`git commit`命令提交到Git的代码仓库。 3. 如何创建一个新的分支并切换到这个分支? 可以使用`git branch`命令创建新分支,然后使用`git checkout`命令切换到新分支: ``` $ git branch new_branch # 创建新分支 $ git checkout new_branch # 切换到新分支 ``` 也可以使用`git checkout`命令的`-b`选项,一步完成创建和切换: ``` $ git checkout -b new_branch # 创建新分支并切换到新分支 ``` 4. 如何合并两个分支? 可以使用`git merge`命令合并两个分支: ``` $ git checkout master # 切换到要合并的分支(通常是主分支) $ git merge feature_branch # 合并另一个分支 ``` 在合并过程中,Git会自动检测两个分支的差异,并尝试自动合并代码。如果合并过程中发生冲突,需要手动解决冲突,然后再次执行`git merge`命令。 5. 如何撤销上一次提交? 可以使用`git revert`命令撤销上一次提交: ``` $ git revert HEAD # 撤销上一次提交 ``` 这会创建一个新的提交,用于撤销上一次提交的变更。如果需要撤销多个提交,可以使用`git revert`命令的`-n`选项,指定要撤销的提交数量。 6. 如何回退到某个提交? 可以使用`git reset`命令回退到某个提交: ``` $ git reset --hard commit_id # 回退到指定的提交 ``` 这会将当前分支回退到指定的提交,并重写工作区和暂存区的内容。这会丢失当前提交之后的所有提交记录,谨慎使用。 7. 如何查看提交历史? 可以使用`git log`命令查看提交历史: ``` $ git log # 查看提交历史 ``` 这会列出所有提交的记录,包括提交的哈希值、作者、时间、提交消息等信息。可以使用`--pretty`选项指定输出格式。 8. 如何查看文件的差异? 可以使用`git diff`命令查看文件的差异: ``` $ git diff file_path # 查看工作区与当前版本库的差异 $ git diff commit_a..commit_b file_path # 查看两个提交之间的差异 ``` 这会输出文件的变更内容,包括添加、修改、删除等操作。如果需要查看某个文件的历史变更记录,可以使用`git log`命令的`--follow`选项。 9. 如何从远程仓库拉取代码? 可以使用`git pull`命令从远程仓库拉取代码: ``` $ git pull origin master # 从远程仓库的主分支拉取代码 ``` 这会将远程仓库的代码拉取到本地,并自动合并到当前分支。如果需要从其他分支拉取代码,可以修改`origin master`为相应的分支名称。 10. 如何推送代码到远程仓库? 可以使用`git push`命令将代码推送到远程仓库: ``` $ git push origin master # 将代码推送到远程仓库的主分支 ``` 这会将当前分支的代码推送到远程仓库,并更新远程仓库的代码。如果需要推送到其他分支,可以修改`origin master`为相应的分支名称。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值