AcWing基础算法课Level-2 第三讲 搜索与图论

举报
小哈里 发表于 2022/05/10 22:21:35 2022/05/10
【摘要】 AcWing基础算法课Level-2 第三讲 搜索与图论 DFS AcWing 842. 排列数字3379人打卡 AcWing 843. n-皇后问题3071人打卡 BFS AcWing 844. ...

AcWing基础算法课Level-2 第三讲 搜索与图论

在这里插入图片描述

DFS
AcWing 842. 排列数字3379人打卡
AcWing 843. n-皇后问题3071人打卡
BFS
AcWing 844. 走迷宫2965人打卡
AcWing 845. 八数码2014人打卡
树与图的深度优先遍历
AcWing 846. 树的重心2457人打卡
树与图的广度优先遍历
AcWing 847. 图中点的层次2412人打卡
拓扑排序
AcWing 848. 有向图的拓扑序列2394人打卡
Dijkstra
AcWing 849. Dijkstra求最短路 I2628人打卡
AcWing 850. Dijkstra求最短路 II2300人打卡
bellman-ford
AcWing 853. 有边数限制的最短路2169人打卡
spfa
AcWing 851. spfa求最短路2134人打卡
AcWing 852. spfa判断负环1990人打卡
Floyd
AcWing 854. Floyd求最短路2096人打卡
Prim
AcWing 858. Prim算法求最小生成树2050人打卡
Kruskal
AcWing 859. Kruskal算法求最小生成树2016人打卡
染色法判定二分图
AcWing 860. 染色法判定二分图1854人打卡
匈牙利算法
AcWing 861. 二分图的最大匹配1752人打卡

搜索与图论

AcWing 842. 排列数字

#include<iostream>
using namespace std;
int n, c[20];
void dfs(int cur){
    if(cur == n){
        for(int i = 0; i < n; i++)cout<<c[i]<<" ";
        cout<<"\n";
    }else for(int i = 1; i <= n; i++){
        int ok = 1;
        for(int j = 0; j < cur; j++)
            if(c[j]==i)ok = 0;
        if(ok){
            c[cur] = i;
            dfs(cur+1);
        }
    }
}
int main(){
    cin>>n;
    dfs(0);
    return 0;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

AcWing 843. n-皇后问题

//c[i]:第i行的皇后放在第几列
#include<iostream>
using namespace std;
int n, c[20], ans;
void dfs(int cur){
    if(cur > n){
		ans++;
		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= n; j++){
				if(c[i]==j)cout<<"Q";
				else cout<<".";
			}
			cout<<"\n";
		}
		cout<<"\n";
	}
    else for(int i = 1; i <= n; i++){
        int ok = 1;
        for(int j = 1; j < cur; j++)
            if(c[j]==i || c[j]-j==i-cur || c[j]+j==i+cur)
                { ok = 0; break; }
        if(ok){
            c[cur] = i;
            dfs(cur+1);
        }
    }
}
int main(){
    cin>>n;
    dfs(1);
    //cout<<ans<<"\n";
    return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

AcWing 844. 走迷宫

#include<bits/stdc++.h>
using namespace std;
const int maxn = 220;
int n, m, a[maxn][maxn], vis[maxn][maxn];
struct node{int x,y,step;};

inline int bfs(){
	int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
	queue<node>q;  q.push({1,1,0});  vis[1][1]=1;
	while(q.size()){
		node t = q.front();  q.pop();
		if(t.x==n&&t.y==m)return t.step;
		for(int i = 0; i < 4; i++){
			int nx = t.x+dx[i], ny = t.y+dy[i];
			if(nx>=1&&nx<=n && ny>=1&&ny<=m &&!a[nx][ny] &&!vis[nx][ny]){
				q.push({nx,ny,t.step+1});
				vis[nx][ny] = 1;
			}
		}
	}
	return -1;
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
			cin>>a[i][j];
	cout<<bfs()<<"\n";
    return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

AcWing 845. 八数码

//令一个棋盘表示一个状态,用字符串维护。转移的时候交换上下左右。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;

int dx[] = {0,0,-1,1};
int dy[] = {1,-1,0,0};
string goal = "12345678x";
unordered_map<string,int>ma;//TLE

int main(){
	ios::sync_with_stdio(false);
	string s;  //cin>>s;
	for(int i=1; i<=9;i++){string x; cin>>x; s=s+x;}
	if(s==goal){cout<<"0\n";return 0;}
	
	queue<string>q;  q.push(s);
	while(q.size()){
		string t = q.front();  q.pop();
		if(t==goal)break;
		int z;
		for(z=0; z < 9; z++)
			if(t[z]=='x')break;
		int x=z/3, y=z%3;
		for(int i = 0; i < 4; i++){
            int nx=x+dx[i], ny=y+dy[i], nz=nx*3+ny;
            if(nx<0||nx>=3||ny<0||ny>=3)continue;
            string tt = t;
            swap(tt[z],tt[nz]);
            if(!ma.count(tt)){
                q.push(tt);
                ma[tt] = ma[t]+1;
            }
        }
	}
	if(ma.count(goal))cout<<ma[goal]<<"\n";
	else cout<<-1<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

AcWing 846. 树的重心

//题目:求将树的重心删除后,剩余各个连通块中点数的最大值
//思路:对于树上的每一个点,计算其所有子树中最大的子树节点数,这个值最小的点就是这棵树的重心。在DFS中计算每个子树的大小,记录“向下”的子树的最大大小,利用总点数-当前子树(这里的子树指有根树的子树)的大小得到“向上”的子树的大小,然后按照定义求重心。
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e5+10;

int n, ans=1e9+10;
vector<int>G[maxn];

//返回以u为根的子树中节点的个数,包括u节点
int vis[maxn];
int dfs(int u){
	vis[u] = 1;
	int sum = 1;//加上u自己
	int res = 0;
	for(int v : G[u]){
		if(vis[v])continue;
		int num = dfs(v);
		res = max(res, num);//更新最大联通子图的节点数
		sum += num;
	}
	res = max(res, n-sum);//更新从上面访问下来的vis过的
	ans = min(ans, res);//更新树的重心
	return sum;
}

int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i = 0; i < n-1; i++){
		int u, v;  cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1);//任意点都行
	cout<<ans<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

AcWing 847. 图中点的层次

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e5+10;

vector<int>G[maxn];
int vis[maxn];

int main(){
	ios::sync_with_stdio(false);
	int n, m; 
	cin>>n>>m;
	for(int i = 1; i <= m; i++){
		int u, v;  cin>>u>>v;
		G[u].push_back(v);
	}
	queue<pair<int,int> >q;  q.push({1,0});
	vis[1] = 1;
	int ans = -1;
	while(q.size()){
		int u = q.front().first, w = q.front().second; q.pop();
		if(u==n){ans=w; break;}
		for(int v:G[u]){
			if(!vis[v]){
				vis[v] = 1;
				q.push({v,w+1});
			}
		}
	}
	cout<<ans<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

AcWing 848. 有向图的拓扑序列

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e5+10;

vector<int>G[maxn];
int in[maxn];

int main(){
	ios::sync_with_stdio(false);
	int n, m; 
	cin>>n>>m;
	for(int i = 1; i <= m; i++){
		int u, v;  cin>>u>>v;
		G[u].push_back(v);
		in[v]++;
	}
	
	vector<int>vc;
	queue<int>q;
	for(int i = 1; i <= n; i++)
		if(in[i]==0)q.push(i);
	while(q.size()){
		int u = q.front();  q.pop();
		vc.push_back(u);
		for(int v:G[u]){
			in[v]--;
			if(in[v]==0)q.push(v);
		}
	}
	if(vc.size()<n){cout<<"-1\n"; return 0;}
	for(int i = 0; i < vc.size(); i++){
		cout<<vc[i]<<" ";
	}
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

AcWing 849. Dijkstra求最短路 I

#include<bits/stdc++.h>
using namespace std;
const int maxn = 550, inf=1e9+10;
int e[maxn][maxn];
int dist[maxn], vis[maxn];
int main(){
	ios::sync_with_stdio(false);
	int n, m;  cin>>n>>m;
	memset(e,0x3f,sizeof(e));
	for(int i = 1; i <= m; i++){
		int u, v, w; cin>>u>>v>>w;
		e[u][v] = min(e[u][v], w);
	}
	
	int s = 1, t = n;
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[s] = 0;
	for(int i = 1; i <= n; i++){
		int u = -1, minn = inf;
		for(int j = 1; j <= n; j++){
			if(!vis[j] && dist[j]<minn){
				u = j; minn = dist[j];
			}
		}
		if(u==-1)break;
		vis[u] = 1;
		for(int j = 1; j <= n; j++){
			if(dist[j]>dist[u]+e[u][j]){
				dist[j] = dist[u]+e[u][j];
			}
		}
	}
	if(dist[t]!=e[505][505])cout<<dist[t]<<"\n";
	else cout<<-1<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

AcWing 850. Dijkstra求最短路 II

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10, inf=1e9+10;
vector<pair<int,int> >G[maxn];
int dist[maxn], vis[maxn];
int main(){
	ios::sync_with_stdio(false);
	int n, m;  cin>>n>>m;
	for(int i = 1; i <= m; i++){
		int u, v, w; cin>>u>>v>>w;
		G[u].push_back({v,w});
	}
	
	int s = 1, t = n;
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	dist[s] = 0;
	priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > >q;
	q.push({0,s});
	while(q.size()){
		int u = q.top().second;  q.pop();
		if(vis[u])continue;
		vis[u] = 1;
		for(int i = 0; i < G[u].size(); i++){
			int v=G[u][i].first, w=G[u][i].second;
			if(dist[v]>dist[u]+w){
				dist[v]=dist[u]+w;
				q.push(make_pair(dist[v],v));
			}
		}
	}
	if(dist[t]!=dist[0])cout<<dist[t]<<"\n";
	else cout<<-1<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

AcWing 853. 有边数限制的最短路

/*
Bellman-Ford:
+ 维护dist[i]表示当前到i的最短路
+ 执行n步(相当于起点出发走n步,所以一定能到终点)。
+ 每次用所有的m条边去松弛当前能到达的最短路(相当于每次从第n步骤的点出发走一下所有的边,更新到所有点的最短路)。
*/
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 510, maxm = 1e5+10;
struct Edge{int u, v, w;}e[maxm];
int dist[maxn], tmp[maxn];
int main(){
	int n, m, k;  cin>>n>>m>>k;
	for(int i = 1; i <= m; i++)
		cin>>e[i].u>>e[i].v>>e[i].w;
	memset(dist,0x3f,sizeof(dist));
	dist[1] = 0;
	for(int i = 1; i <= k; i++){
		memcpy(tmp,dist,sizeof(dist));
		for(int j = 1; j <= m; j++){
			dist[e[j].v] = min(dist[e[j].v], tmp[e[j].u]+e[j].w);
		}
	}
	if(dist[n]>dist[505]/2)cout<<"impossible\n";//考虑存在边(x,n)但是没有边(1,x),用(x,n)更新(1,n)的距离后会使得(1,n)<inf,但是实际上还是无法到达n的
	else cout<<dist[n]<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

AcWing 851. spfa求最短路

/*
给定一张有向/无向图,求s到所有点的最短路。
对于每个点i,我们记f[i]表示目前s到i的最短路,初始时为正无穷。
初始时将s加入队列,每次取出队首元素,用它更新别的点的f值。如果一个点的f值变小了并且它不在队列中,就将它加入队列。队列为空时结束。
如果不存在负权环,那么每个点最多加入队列n-1次。
*/
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
const int maxm = 1e5+10;

//Grape
int n, m;
struct Edge{int v, w, next;}e[maxm<<1];
int tot, head[maxn];
void AddEdge(int u, int v, int w){
    tot++; e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot;
}

//SPFA
int dist[maxn], book[maxn];//book[i]表示当前i是否在队列中
queue<int>q;
void spfa(){
    for(int i = 0; i <= n; i++)dist[i]=2147483647;
    dist[1]=0; book[1]=1; q.push(1);
    while(q.size()){
        int u = q.front();  q.pop();  book[u]=0;
        for(int i = head[u]; i > 0; i = e[i].next){
            int v = e[i].v, w = e[i].w;
            if(dist[v]>dist[u]+w){
                dist[v] = dist[u]+w;
                if(!book[v]){
                    book[v] = 1;  q.push(v);
                }
            }
        }
    }
}

int main(){
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y, z; cin>>x>>y>>z; AddEdge(x,y,z);
    }
    spfa();
    if(dist[n]>dist[0]/2)cout<<"impossible\n";
	else cout<<dist[n]<<"\n";
    return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

AcWing 852. spfa判断负环

//cnt[i]表示编号为i的节点是第几个加入路径的节点
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2e3+10;
const int maxm = 1e5+10;

//Grape
int n, m;
struct Edge{int v, w, next;}e[maxm<<1];
int tot, head[maxn];
void AddEdge(int u, int v, int w){
    tot++; e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot;
}

//SPFA
int dist[maxn], book[maxn], cnt[maxn];
queue<int>q;
bool spfa(){
    memset(dist,0x3f,sizeof(dist));
	for(int i = 1; i <= n; i++){ q.push(i); book[i]=1;} 
    while(q.size()){
        int u = q.front();  q.pop();  book[u]=0;
        for(int i = head[u]; i > 0; i = e[i].next){
            int v = e[i].v, w = e[i].w;
            if(dist[v]>dist[u]+w){
                dist[v] = dist[u]+w;
				cnt[v] = cnt[u]+1;
				if(cnt[v]>n-1)return true;
                if(!book[v]){
                    book[v] = 1;  q.push(v);
                }
            }
        }
    }
	return false;
}

int main(){
    cin>>n>>m;
    for(int i = 1; i <= m; i++){
        int x, y, z; cin>>x>>y>>z; AddEdge(x,y,z);
    }
    if(spfa())cout<<"Yes\n";
	else cout<<"No\n";
    return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

AcWing 854. Floyd求最短路

#include <bits/stdc++.h>
using namespace std;
const int maxn = 210;
int e[maxn][maxn];
int main(){
	int n, m, q;
	cin>>n>>m>>q;
	memset(e,0x3f,sizeof(e));
	for(int i = 1; i <= n; i++)e[i][i]=0;
	for(int i = 1; i <= m; i++){
		int x, y, z;  cin>>x>>y>>z;
		e[x][y] = min(e[x][y], z);
	}
	for(int k = 1; k <= n; k++)
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
	for(int i = 1; i <= q; i++){
		int x,y;  cin>>x>>y;
		if(e[x][y]>e[201][201]/2)cout<<"impossible\n";
		else cout<<e[x][y]<<"\n";
	}
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

AcWing 858. Prim算法求最小生成树

/*
Prim:
dist[i]维护节点i到生成树集合S的最短距离,每次找到最近的加入生成树,然后用该节点的所有直接相连边的更新生成树外的点到生成树的距离。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 550, inf=0x3f3f3f3f;
int n, m, e[maxn][maxn];
int dist[maxn], vis[maxn];
int prim(){
	for(int i = 1; i <= n; i++)dist[i] = e[1][i];
	vis[1] = 1;
	int ans = 0;
	for(int i = 2; i <= n; i++){
		int t = -1;
		for(int j = 1; j <= n; j++){
			if(!vis[j] && (t==-1||dist[t]>dist[j])){
				t = j;
			}
		}
		if(dist[t] == inf)return inf;
		ans += dist[t];
		vis[t] = 1;
		for(int j = 1; j <= n; j++)
			dist[j] = min(dist[j], e[t][j]);
	}
	return ans;
}
int main(){
	cin>>n>>m;
	memset(e,0x3f,sizeof(e));
	for(int i = 1; i <= n; i++)e[i][i] = 0;
	for(int i = 1; i <= m; i++){
		int u, v, w;  cin>>u>>v>>w;
		e[u][v] = e[v][u] = min(e[u][v],w);
	}
	int t = prim();
	if(t==inf)cout<<"impossible\n";
	else cout<<t<<"\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

AcWing 859. Kruskal算法求最小生成树

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;

struct node{int u, v, w; }e[maxn];
bool cmp(node a, node b){return a.w<b.w;}

int fa[maxn+10];
void init(int n){for(int i = 1; i <= n; i++)fa[i]=i;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(int x, int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}
int count(int n){int cnt=0; for(int i = 1; i <= n; i++)if(fa[i]==i)cnt++;return cnt;}

int main(){
	ios::sync_with_stdio(false);
	int n, m;  cin>>n>>m;
	for(int i = 1; i <= m; i++){
		cin>>e[i].u>>e[i].v>>e[i].w;
	}
	sort(e+1,e+m+1,cmp);
	int ans = 0, cnt = 0;  init(n);
	for(int i = 1; i <= m; i++){
		if(find(e[i].u)!=find(e[i].v)){
			merge(e[i].u,e[i].v);
			ans += e[i].w;
			cnt++;
		}
	}
	if(cnt==n-1)cout<<ans<<"\n";
	else cout<<"impossible\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

AcWing 860. 染色法判定二分图

/*
二分图染色:
+ 将所有点分成两个集合,使得所有边只出现在集合之间,就是二分图
+ dfs遍历所有点,每次将未染色的点进行染色,如果存在相邻两个点颜色相同就不是而二分图。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
vector<int>G[maxn];
int col[maxn];
int dfs(int u, int color){
	col[u] = color;
	for(int v:G[u]){
		if(!col[v]){
			if(!dfs(v,3-color))return false;
		}else{
			if(col[u]==col[v])return false;
		}
	}
	return true;
}

int main(){
	int n, m;  cin>>n>>m;
	for(int i = 1; i <= m; i++){
		int x, y;  cin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	int ok = 1;
	for(int i = 1; i <= n; i++){
		if(!col[i]){
			if(!dfs(i,1)){
				ok = 0;
				break;
			}
		}
	}
	if(ok==1)cout<<"Yes\n";
	else cout<<"No\n";
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

AcWing 861. 二分图的最大匹配

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int N = 550;
vector<int>G[N];
int po[N], book[N], ans;//po[v]表示点v当前的匹配对象。
int find(int u){
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];
        if(!book[v]){//不在交替路中
            book[v] = 1;//放入交替路
            if(po[v]==0||find(po[v])){//当前点未用或最终未用,交替路是增广路。
                po[v] = u;//匹配成功
                return true;
            }
        }
    }
    return false;
}
int main(){
    int nl, nr, m;
    cin>>nl>>nr>>m;
    for(int i = 1; i <= m; i++){
        int x, y;  cin>>x>>y;
        G[y].push_back(x);
    }
    for(int i = 1; i <= nr; i++){
        memset(book,0,sizeof(book));
        if(find(i)){
            ans++;
        }
    }
    cout<<ans<<"\n";
    //for(int i = 1; i <= nl; i++)cout<<po[i]<<" ";
    return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

文章来源: gwj1314.blog.csdn.net,作者:小哈里,版权归原作者所有,如需转载,请联系作者。

原文链接:gwj1314.blog.csdn.net/article/details/115107632

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。