题目描述
在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件:
- 路径上的所有点的出边所指向的点都直接或间接与终点连通.
- 在满足条件1的情况下使路径最短。
- 注意:图 G 中可能存在重边和自环,题目保证终点没有出边。
请你输出符合条件的路径的长度。
输入输出格式
输入格式:
第一行有两个用一个空格隔开的整数 n 和 m,表示图有 n 个点和 m 条边。
接下来的 m 行每行 2 个整数 x,y。之间用一个空格隔开,表示有一条边从点 x 指向点y。
最后一行有两个用一个空格隔开的整数 s,t,表示起点为 s,终点为 t。
输出格式:
输出只有一行,包含一个整数,表示满足题目描述的最短路径的长度。如果这样的路径不存在,输出 -1 。
简吸
模拟赛的时候实在是想不到怎么找。然后写了个floyed上去。骗了10分。
赛后看洛谷题解的时候,就感觉让人十分 niupi。
大概是这样:
我们可以将全部的点分为以下三类:
1.指向的点也能连接终点。
2.自己联通终点。
3.在图G上的点。
感觉这题的核心是建一个反向图筛点。
显然 3 类点已经读入,那么接下来是筛选 2 类点。
做法就是从终点开始广搜(反向图),搜到的做个标记就是2号店。
如果终点没有标记直接 return 0。
接下来是找 1 类点,做法是在有 2 类点中进行暴搜,对于 2 类点所连接的点进行判断,如果连接点不是 2 类点,那么这个点就不是 3 类点。
最后再用广搜找最短路。
xxxxxxxxxx51 1#include2#include3using namespace std;45#define N 501067bool cha[N];8int n, a[N];9int now, ans1 = 0x3f3f3f3f, ans2, tot;10char ch;1112int main()13{14 cin >> n;15 for(int i = 1; i <= n; i ++)16 {17 cin >> ch;18 if(ch == ‘F’)19 a[i] = 1;20 }21 for(int k = 1; k <= n; k ++)//遍历区间长度22 {23 memset(cha, 0, sizeof(cha));24 int flag = 1, tot = 0, now = 0;//now表示这一段区域是否翻转25 for(int i = 1; i <= n; i ++)26 {27 now ^= cha[i];//遇到变化区间的末尾时,再变回来28 if(a[i] ^ now == 0)29 {30 if(i + k - 1 > n)//超出范围31 {32 flag = 0;33 break; 34 }35 tot ++;36 cha[i + k] ^= 1;37 now ^= 1;38 }39 }40 if(flag == 1)41 {42 if(tot < ans1)//记录一下再少变化数量43 {44 ans1 = tot;45 ans2 = k;46 }47 }48 }49 cout << ans2 << “ “ << ans1 << endl;50 return 0;51}cpp
1 |
|
话说这段代码用控制变量法调了好久
2022-05-03 14:58:24