Week 9 啥也不是()

1.P3367 【模板】并查集

并 + 查 

详见注释

#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 1e4+5;
int f[MAX_N];

int father(int x)//查找根节点
{
    if(f[x] != x)
        f[x] = father(f[x]);
    return f[x];
}

void connect(int a,int b)//合并两个集合
{
    int roota = father(a);
    int rootb = father(b);
    if(roota != rootb)
        f[roota] = rootb;
}

int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        f[i] = i;//初始化父节点为自身

    for(int i=1;i<=m;i++){
        int z,x,y;
        cin>>z>>x>>y;
        if(z == 1){
            connect(x,y);
        }
        else{
            if(father(x) == father(y))
                cout<<'Y'<<endl;
            else
                cout<<'N'<<endl;
        }
    }
    return 0;
}

2.P8604 [蓝桥杯 2013 国 C] 危险系数

选用DFS

分别记录(1)起点到终点的路径总数 (2)某点在起点到终点的所有路径中的出现次数

(1)==(2)时,该点一定是起点和终点之间的关键点。

#include <bits/stdc++.h>
using namespace std;

int n,m;
vector<int> a[1005];//所有与i相连的点
int vis[1005],ans[1005];//ans[]表示点i在起点到终点的所有路径中出现了多少次
int s,e,c,res,sum;//sum:起点到终点的路径总数

void dfs(int df)
{
    if(df == e){
        sum++;
        for(int i=1;i<=c;i++){
            ans[i] += vis[i]?1:0;
        }
        return ;
    }
    vis[df] = 1;
    for(auto to:a[df]){
        if(vis[to]) continue;
        dfs(to);
    }
    vis[df] = 0;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        a[u].push_back(v);
        a[v].push_back(u);
        c = max(max(c,u),v);
    }

    cin>>s>>e;
    dfs(s);
    for(int i=1;i<=c;i++)
        if(ans[i] == sum)
            res++;

    cout<<res-1;
    return 0;
}

3.P1330 封锁阳光大学

染色问题:要使每一条边的两点被染成两种不同的颜色,否则,impossible。

#include <bits/stdc++.h>
using namespace std;

vector<int> g[10010];
int color[10010];
int color2[10010];
int n, m;
bool ok;

int dfs(int i, int s){
    if (!ok) return 0;
    int sum = s;
    color[i] = s;
    for (int j = 0; j < g[i].size(); j++){
        int v = g[i][j];
        if (color[v] == -1){
            color[v] = (!s);
            sum += dfs(v, !s);
        } else if (color[v] == s) {
            ok = false;
        }
    }
    return sum;
}

int main(){
    cin >> n >> m;
    for (int i = 0; i < m; i++){
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    
    memset(color, -1, sizeof(color));
    ok = true;
    int ans = 0;
    for (int i = 1; i <= n; i++){
        if (color[i] == -1){
            memcpy(color2, color, sizeof(color));
            int a = dfs(i, 0);
            memcpy(color, color2, sizeof(color));
            int b = dfs(i, 1);
            ans += min(a, b);
        }
        if (!ok) break;
    }
    
    if (!ok){
        cout << "Impossible" << endl;
    } else {
        cout << ans << endl;
    }

    return 0;
}

4.P3916 图的遍历

反向建边(蒟蒻新学的)+ DFS

反向建边:题目要求能到达的编号最大的点,可以反向考虑较大的点能够到达哪些点

​
#include <bits/stdc++.h>
using namespace std;

int n,m;
vector<int> arr[1005];//存图
int ans[1005];

void dfs(int x,int y)
{
    if(ans[x])
        return ;//已经来过
    ans[x] = y;
    for(int i=0;i<arr[x].size();i++)
        dfs(arr[x][i],y);
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        arr[v].push_back(u);//有向图反向建边
    }

    for(int i=n;i>=1;i--)
        dfs(i,i);

    for(int i=1;i<=n;i++){
        cout<<ans[i];
        if(i!=n) cout<<' ';
    }
    return 0;
}

5.P1119 灾后重建

原题指路:P1119 灾后重建 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1119 

请看VCR 代码

#include<iostream>
#include<cstdio>
#define N 205
using namespace std;
int n,m;
int a[N];
int f[N][N];//邻接矩阵存边
inline void updata(int k){
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	if(f[i][j]>f[i][k]+f[j][k])
	f[i][j]=f[j][i]=f[i][k]+f[j][k];//用这个新的更新所有前面的 
	return;
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
	scanf("%d",a+i);//依次输入每一个村庄建立完成时需要的时间
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++){
		f[i][j]=1e9;//初始化为保证它不爆炸范围内的最大值 
	}
	for(int i=0;i<n;i++)
	f[i][i]=0;
	int s1,s2,s3;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&s1,&s2,&s3);
		f[s1][s2]=f[s2][s1]=s3;//初始化边长 
	}
	int q;
	cin>>q;
	int now=0;
	for(int i=1;i<=q;i++){//处理各询问 
		scanf("%d%d%d",&s1,&s2,&s3);
		while(a[now]<=s3&&now<n){
			updata(now);//依次更新点,使它可以被用来更新其他的点 
			now++;
		}
		if(a[s1]>s3||a[s2]>s3)cout<<-1<<endl;
		else {
			if(f[s1][s2]==1e9)cout<<-1<<endl;
			else cout<<f[s1][s2]<<endl;
		}
	}
	return 0;
} 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

棠梨下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值