题目链接:点击查看
题目大意:给出一个由n个点及m条边组成的无向图,现在要求从点1出发,到达点n,再回到点1,一路上经过尽可能多的点,并且保证除了起点和终点外的每个点至多只能经过一次,并输出路径
题目分析:从点1出发到点n再回到点1,这个题目之前做过类似的,不过那个题目是要求最短路,用的是最小费用最大流,回到这个题目来看,要求尽可能多的经过点,也就说明每个点对答案的贡献为1,所以要用最大费用最大流,而权值在点上,很自然的想到需要拆点限流,所以建图方式就出来了:
- 源点->点1入点,流量为2,花费为0
- 点1入点->点1出点,流量为2,花费为1
- 点n入点->点n出点,流量为2,花费为1
- 其余点入点->其余点出点,流量为1,花费为1
- 某个点的出点->对应连边点的入点,流量为1,花费为0
- 点n出点->汇点,流量为2,花费为0
如此建图后,直接跑最大费用最大流就可以进一步判断了,现在可以得到了一个ans代表的最大花费,以及max_flow代表最大流,显然当最大流等于2的时候说明可以在原图中找到两条不想交的从起点到终点的路径,此时的花费为ans-2,因为起点和终点被计算了两次,所以减去2就好了,max_flow不等于2的时候直接输出No Solution!就好了,但是真的是这样吗?如果这样判断交上去有一个测试点过不去,这就是这个题目的一个小坑了,如果整张图中只有一条路径是从点1直接到点n的,这样的图虽然max_flow等于1,但是却是符合条件的特例,需要特判一下
现在只是判断出是否有解,最后还需要输出路径,其实直接跑dfs就好了,因为每条连边的流量都设置为1,所以如果这条边对答案做出了贡献,那么他的流量就会变成0,对于每个点寻找一下他的下一个符合要求的点,一路寻找,从起点找到终点就好了,记得用一个vis数组标记一下哪些点已经使用过了,因为对于每个点至多只能使用一次嘛,第一遍dfs正序输出,第二遍dfs倒序输出,写法类似于树的前序遍历和后序遍历,剩下的对于细节仔细处理一下就好了
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include