P1330 封锁阳光大学
题目描述
曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由 n个点构成的无向图,n个点之间由 m 条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。
询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
输入格式
第一行两个正整数,表示节点数和边数。 接下来 m 行,每行两个整数 u,v,表示点 u 到点 v之间有道路相连。
输出格式
仅一行如果河蟹无法封锁所有道路,则输出 Impossible
,否则输出一个整数,表示最少需要多少只河蟹。
输入输出样例
输入 #1复制
3 3 1 2 1 3 2 3
输出 #1复制
Impossible
输入 #2复制
3 2 1 2 2 3
输出 #2复制
1
说明/提示
1.注意这个可能是非连通图,每一个点都需要搜索
2.相当于一个染色问题,用1黑色代表该点有河蟹,0白色代表没有河蟹,要求同一条边上的两个点颜色不能相同
3.分别用1和0染色搜索的话需要注意每搜索一次,需要对是否染过色复位
4.Impossible是大写的
#include<bits/stdc++.h>
using namespace std;
vector<int> graph[10003];
int color[10003];
int reset[10003];
int n, m;
bool flag;//判断有没有答案
int dfs(int i, int col) {
if (!flag) return 0;
int sum = col;//sum计算的是染1的点的个数,如果开始染的是1这个颜色,直接计数为1,如果开始染的是0这个颜色的话就计数为0
color[i] = col;
for (int j = 0; j < graph[i].size(); j++) {
int v = graph[i][j];
if (color[v] == -1) {//该点没有被染过
color[v] = (!col);//染上相反的颜色(0,1)
sum += dfs(v, !col);
}
else if (color[v] == col)//该点颜色与相邻的点颜色相同
flag = false;
}
return sum;
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
memset(color, -1, sizeof(color));
flag = true;
int ans = 0;
for (int i = 1; i <= n; i++) {//非连通图的话每个点都要搜一下
if (color[i] == -1) {
memcpy(reset, color, sizeof(color));//用reset数组记录color数组的值,为染色为1的搜索初始化用
int a = dfs(i, 0);//染0这个颜色搜索一遍
memcpy(color, reset, sizeof(color));//初始化
int b = dfs(i, 1);//染1这个颜色搜索一遍
ans += min(a, b);//取最小值
}
if (!flag) break;
}
if (!flag) cout << "Impossible" << endl;
else cout << ans << endl;
return 0;
}
其他参考
题解 P1330 【封锁阳光大学】 - KesdiaelKen 的博客 - 洛谷博客 (luogu.com.cn)
上面这个会用到链式存图
链式前向星——最完美图解 - 腾讯云开发者社区-腾讯云 (tencent.com)
题解 P1330 【封锁阳光大学】 - EricWay1024 - 洛谷博客 (luogu.com.cn)
P8604 [蓝桥杯 2013 国 C] 危险系数
题目背景
抗日战争时期,冀中平原的地道战曾发挥重要作用。
题目描述
地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
我们来定义一个危险系数 DF(x,y)DF(x,y):
对于两个站点 xx 和 y(x\neq y),y(x=y), 如果能找到一个站点 zz,当 zz 被敌人破坏后,xx 和 yy 不连通,那么我们称 zz 为关于 x,yx,y 的关键点。相应的,对于任意一对站点 xx 和 yy,危险系数 DF(x,y)DF(x,y) 就表示为这两点之间的关键点个数。
本题的任务是:已知网络结构,求两站点之间的危险系数。
输入格式
输入数据第一行包含 22 个整数 n(2 \le n \le 1000)n(2≤n≤1000),m(0 \le m \le 2000)m(0≤m≤2000),分别代表站点数,通道数。
接下来 mm 行,每行两个整数 u,v(1 \le u,v \le n,u\neq v)u,v(1≤u,v≤n,u=v) 代表一条通道。
最后 11 行,两个数 u,vu,v,代表询问两点之间的危险系数 DF(u,v)DF(u,v)。
输出格式
一个整数,如果询问的两点不连通则输出 -1−1。
输入输出样例
输入 #1复制
7 6 1 3 2 3 3 4 3 5 4 5 5 6 1 6
输出 #1复制
2
说明/提示
时限 1 秒, 64M。蓝桥杯 2013 年第四届国赛
z是x和y的关键点说明从x到y的每一条路径都要经过z。
则只需要计算从x走到y一共有多少条路径,每找到一条路径就让这条路径上每个点访问次数加1。
若某点z被访问次数等于x和y之间的路径总数,那么该点就是关键点。(因为从x到y的每一条路径都要访问z点)
#include<bits/stdc++.h>
using namespace std;
int n, m;
int visit[1003];
vector <int> g[1003];
int bg, ed,num,cnt[1003],ans;
void dfs(int pos) {
if (pos == ed) {
num++;//路径数目加一
for (int i = 1; i <= n; i++) {
if (visit[i])cnt[i]++;//访问次数加1
}
return;
}
for (int i = 0; i < g[pos].size(); i++) {
int next = g[pos][i];
if (!visit[next]) {
visit[next] = 1;
dfs(next);
visit[next] = 0;//复原重新搜索
}
}
return;
}
int main() {
cin >> n >> m;
for (int i = 0; i <m; i++) {
int x, y;
cin >> x >> y;
g[y].push_back(x);
g[x].push_back(y);
}
cin >> bg >> ed;
visit[bg] = 1;//标记起点访问过
dfs(bg);
for (int i = 1; i <= n; i++) {
if (cnt[i] == num)
ans++;
}
ans -= 2;//不包括起点和终点
cout << ans;
return 0;
}
P3916 图的遍历
题目描述
给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v出发,能到达的编号最大的点。
输入格式
第 1行 2 个整数 N,M表示点数和边数。
接下来 M 行,每行 2 个整数 U_i,V_i,表示边 (Ui,Vi)。点用 1,2,…,N 编号。
输出格式
一行 N 个整数 A(1),A(2),…,A(N)。
输入输出样例
输入 #1复制
4 3 1 2 2 4 4 3
输出 #1复制
4 4 3 4
说明/提示
若要找该点能到达的最大编号点,那么只用看最大编号点的起点集合里面有没有该点就可以了。从最大点开始搜索。
#include<bits/stdc++.h>
using namespace std;
int n, m,ans[100003];
vector <int> g[100003];
void dfs(int st, int ed) {//st:起始点;ed:终点
if (ans[st] > 0)return;//访问过 ,说明该点能够到达编号更大的点
ans[st] = ed;//将ed作为st能够到达的点(即标记为已访问)
for (int i = 0; i < g[st].size(); i++) {
dfs(g[st][i], ed);//依次找以ed为终点的起点g[st][i],并赋值标记为已访问
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int x, y;
cin >> x >> y;
g[y].push_back(x);
}
for (int i = n; i > 0; i--) {//从最大的点开始搜索
dfs(i, i);//点i肯定是能够以它自身作为终点的
}
for (int i = 1; i <= n; i++)cout << ans[i] << ' ';
}