NEUQ-ACM预备队Week5-存图

危险系数

题目

在这里插入图片描述
在这里插入图片描述

实现

计算u,v之间的危险系数,就是要找到从u到v的全部路径中都会经过的点

我们可以通过:记录从u到v的路径数、记录每条路径经过的结点(令节点的值加一),最后如果有节点的值等于路径数时,表明这个节点就是一个危险系数,再找出所有这样的节点即可

代码块

#include<iostream>
#include<vector>
using namespace std;
const int N = 1005;
int n, m;
vector<int> map[N];
bool mapcheck[N];
int mapway[N];
int ans, st, ed;
void DFS(int now)
{
	if (now == ed)
	{
		ans++;
		for (int i = 1; i <= n; i++)
		{
			if (mapcheck[i])
			{
				mapway[i]++;
			}
		}
		return;
	}
	for (int i = 0; i < map[now].size(); i++)
	{
		int to = map[now][i];
		if (!mapcheck[to])
		{
			mapcheck[to] = 1;
			DFS(to);
			mapcheck[to] = 0;
		}
	}
	return;
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b;
		cin >> a >> b;
		map[a].push_back(b);
		map[b].push_back(a);
	}

	cin >> st >> ed;
	mapcheck[st] = 1;
	DFS(st);
	int cnt=0;
	for (int i = 1; i <= n; i++)
	{
		if (mapway[i] == ans)
		{
			cnt++;
		}
	}
	cout << cnt-2;
	return 0;
}

图的遍历

题目

在这里插入图片描述

实现

虽然题目表述为对每一个点v找到它能到达的编号最大的点,但是这种情况下需要判断它的每个终点孰大,所以我们利用反向存图,从大到小,给每个点填入其起点的值,这样最终点的值就必定是它的最大值

代码块

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
vector<int> map[maxn];
int ans[maxn];
//反向建边 从编号最大的数开始,反向搜图
//将这个点能到达的全部点上的ans赋上这个点的值
//同时比较是否比它之前赋得的值大
void DFS(int now, int max)
{
	if (ans[now])return;
	ans[now] = max;	
	for (int i = 0; i < map[now].size(); i++)
	{		
		DFS(map[now][i], max);
	}
}
int main()
{
	cin >> n >> m;
	while (m--)
	{
		int a, b;
		//表示能从a到b,反向建边,令其从b到a;
		cin >> a >> b;
		map[b].push_back(a);
	}
	for (int i = n; i >= 1; i--)
	{
		//这里的两个参数与通常DFS只传出发点的情况不同
		//这里类似于excel的绝对与相对应用,第二个参数令其为绝对引用值
		DFS(i,i);
	}
	for (int i = 1; i <= n; i++)
		printf("%d ", ans[i]);
	return 0;
}

封锁阳光大学

题目

在这里插入图片描述
在这里插入图片描述

实现

因为要封锁全部的路,所以我们可以利用for循环,从每一个点开始,遍历它所能到达的全部点。如何实现封锁路呢?因为河蟹有冲突,但是一条路总是有两个端点的,我们可以设置有河蟹1和河蟹2,在一个点若放置河蟹1,则将下一个点转为放置河蟹2而不是置为空,最后在河蟹的最终数目中加上河蟹1和河蟹2中较小的那个保证最终河蟹数目是最小的,同时,这种情况由于会对全部的点进行涂色,那么无解的情况就是有一条路上的两个端点被涂上了相同颜色

代码块

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + 5;
int n, m;
vector<int> map[maxn];
//check是否被走过,走过的点总是被涂过色的,无需继续涂色
bool mapcheck[maxn];
int ans[maxn];
//河蟹1和河蟹2的计数器
int cnt1, cnt2;
//最终河蟹数
int num;
void DFS(int now, int color)
{
	if (mapcheck[now])return;
	mapcheck[now] = true;
	ans[now] = color;
	//记录涂色种类
	if (ans[now] == 1) cnt1++;
	if (ans[now] == 2) cnt2++;
	for (int i = 0; i < map[now].size(); i++)
	{
		int to = map[now][i];
		if (mapcheck[to])continue;
		//每次涂色时都需要注意色彩的转置,1变2,2变1
		if (color == 1)color = 2;
		else color = 1;
		DFS(to, color);
		if (color == 1)color = 2;
		else color = 1;
	}
}
int main()
{
	cin >> n >> m;
	while (m--)
	{
		int a, b;
		cin >> a >> b;
		//双向图存图
		map[a].push_back(b);
		map[b].push_back(a);
	}
	for (int i = 0; i < n; i++)
	{
	  //点不存在或者已被遍历
		if (map[i].empty() || mapcheck[i])continue;
		DFS(i, 1);
		num += min(cnt1, cnt2);
		cnt1 = 0;
		cnt2 = 0;
	}
	//判断是否有邻接点被涂同一种颜色
	int flag = 1;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j< map[i].size(); j++)
		{
			if (ans[i] == ans[map[i][j]])
				flag = 0;
		}
	}
	if (flag)
		printf("%d", num);
	else printf("Impossible");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值