华为2016某比赛初赛, 傻X做法不能看

突然600多阅读我慌了。。感觉浪费大家赞了……

题目是http://codecraft.huawei.com/       2016年初赛的题,类似TSP问题的那个……。


思路如下: 搜。

然后就傻乎乎搜炸了啊。。。


tarjan缩点后,DP剪枝去掉非法解(能去掉非常多的)。

结果依然是大数据出不了解。。。 所以我的方法非常烂啦


===================================

我们自以为很厉害的方法~实际上很垃圾,初赛20多分的样子,显然被刷啦~~~


但是毕竟做了。。代码保留一下就好了


往事不堪回首。。也不想读代码了。。直接看代码注释。。 这篇文章应该没人看吧…… 自己留纪念



#include "CheckMap.h"
#include 
#include 
using namespace std;
//已经开启了using namespace std了

unsigned long long start = clock();
CheckMap check(1, 1);
unsigned short final_ans = 1000; //默认初始最小答案
unsigned short edge_ans[max_vertex_num] = {0}, edge_ans_size = 0;
unsigned short tmp_edge[max_vertex_num];
ImportantMap init_next[max_vertex_num], final_status;
//6|28|34|8|21|15|25|10|13|14|31
void dfs(Vertex current_vertex, ImportantMap current_map, unsigned short current_ans, unsigned short deep)
{
	if ( ((clock() - start) / (double)CLOCKS_PER_SEC) > 9.3)	return;
	if (current_ans >= final_status)	return;
	if (!check.check(current_vertex))	return; //查看这个节点是否能搜出来
	//cout << current_vertex << " " << current_map <<" " << current_ans << " " << deep << endl;
	if (current_vertex == check.end_vertex)//已经搜到终点啦
	{
		//因为有确保性原因,所以一定已经是解了?! 这个一会儿需要检测一下正确性

		if (((current_map & final_status) == final_status) && current_ans < final_ans)
		{
			//cout << current_vertex << " " << current_map <<" " << current_ans << " " << deep << endl;
			final_ans = current_ans;
			edge_ans_size = deep;
			memmove(edge_ans, tmp_edge, sizeof(short) * deep);
			cout << final_ans << endl;
			//for (int i = 0; i != edge_ans_size; ++ i)
			//	cout << edge_ans[i]<<" ";	cout << endl;

		}
		return;
	}
	vis[current_vertex] = true; //访问标记
	for (int i = 0; i != check.g[current_vertex].size(); ++ i)
	{
		Vertex will_vertex = check.g[current_vertex][i];
		//cout << will_vertex << endl;
		if (vis[will_vertex])	continue;//显然,已经访问过的,就不用访问
		//cout << current_map <<" " << init_next[will_vertex]<<" " << final_status << endl;
		if (((current_map | init_next[will_vertex]) & final_status) != final_status)	continue;
		tmp_edge[deep] = check.getEdgeNum(current_vertex , will_vertex);
		if (will_vertex <= check.total_importan_vertex)
		{
			dfs(	will_vertex, 
					current_map | (1<<(will_vertex - 1)), 
					current_ans + check.getDistance(current_vertex, will_vertex), 
					deep + 1);	
		}
		else 			dfs(	will_vertex, 
					current_map,//只保存访问过的重要点地图 
					current_ans + check.getDistance(current_vertex, will_vertex), 
					deep + 1);	
	}
	vis[current_vertex] = false;
}

void init()
{
	freopen("input.txt", "r", stdin);
	int n, m;
	cin >> n >> m;//点总数,边总数
	for (int i = 0; i != m; ++ i)
	{
		unsigned short a, b, c, d;
		cin >> a >> b >> c >> d;
		check.insert(b, c, d, a); //b->c 距离是d,编号是a
	}
	unsigned short zhongyaodian;
	cin >> zhongyaodian;


	/*
	 * Init
	 * 把Map.h里的部分元素,进行清理。
	 * 修改起点, 终点,重要点的总量, 所有点的总量这4个参数
	 * */
	check.setEndVertex(zhongyaodian); //设置重要的点的总量(终点)
	check.setTotalVertex(n); //设置总的点的数量
	check.setTotalImportanVertex(zhongyaodian); //设置重要点的总量
	final_status = (1 << zhongyaodian) - 1;//全部访问完的状态

	check.check(1);
	for (int i = 1; i <= check.total_vertex; ++ i)
		init_next[i] = check.f[check.belong[i]];
}

int main()
{
	init();

	//cout << final_status << endl;
	dfs(1, 1, 0, 0);
	for (int i = 0; i != edge_ans_size; ++ i)
		cout << edge_ans[i]<<" ";	cout << endl;
	


	cout <<"this program runing-time is: "<< ((clock() - start) / (double)CLOCKS_PER_SEC) << " s, and the final distance is " <

checkmap.h

#include "Map.h"

bool vis[max_vertex_num];


class CheckMap:public Map  //生成一个Check变量,来完成所有的check操作
{
	public:

	unsigned short belong[max_vertex_num]; //原来每个点,所属的连通块
	ImportantMap f[max_vertex_num];//f[i]表示i后继能到的点,包括自己

	CheckMap(Vertex start, Vertex end):Map(start, end)
	{
		memset(vis, false, sizeof(vis));
		clear();
	}	

	void clear() //清理tarjan和BFS运算所需要的数组元素
	{
		memset(DFN, 0, sizeof(DFN));
		memset(LOW, 0, sizeof(LOW));
		memset(instack, 0, sizeof(instack));
		memset(my_stack, 0, sizeof(my_stack));
		memset(f, 0, sizeof(f));
		memset(f_self, 0, sizeof(f_self));
		memset(belong, 0, sizeof(belong));
		memset(f_vis, false, sizeof(f_vis));//点是否被访问过,每个点只会被访问一次。(讲道理是这样)
		Stop = din = count = 0;
	}

	
	void tarjan(Vertex current_vertex)
	{
		//cout << current_vertex << endl;
		LOW[current_vertex] = DFN[current_vertex] = ++ din;
		my_stack[++ Stop] = current_vertex;
		instack[current_vertex] = true;
		for (int i = 0; i != g[current_vertex].size(); ++ i)
		{
			Vertex will_vertex = g[current_vertex][i];
			if (vis[will_vertex])	continue;//这个点已经在地图中被移除了
			if (!DFN[will_vertex])
			{
				tarjan(will_vertex);
				LOW[current_vertex] = min(LOW[current_vertex], LOW[will_vertex]);
			}
			else if (instack[will_vertex])	LOW[current_vertex] = min(LOW[current_vertex], DFN[will_vertex]);
		}
		if (LOW[current_vertex] == DFN[current_vertex])
		{
			Vertex tmp;
			++count;
			do
			{
				tmp = my_stack[Stop --];
				instack[tmp] = false;
				belong[tmp] = count;
				if (tmp <= total_importan_vertex)//属于重要点的范畴
				{
					f[count] |= 1 << (tmp - 1); //f[count]这个连通块多了一些元素
				}
			}while (tmp != current_vertex);
		}
	}

	//版本0.01的getF,看看能不能成功
	ImportantMap getF(Vertex current_vertex)
	{
		if (f_vis[current_vertex] == true)	return f[current_vertex];
		f_vis[current_vertex] = true;	//访问标记
		if (current_vertex == belong[end_vertex])//如果已经到了end_vertex,那么显然不能走动了
		{
			return f[belong[end_vertex]];
		}
		for (int i = 0; i != new_g[current_vertex].size(); ++ i)
		{
			f[current_vertex] |= getF(new_g[current_vertex][i]);
		}
		return f[current_vertex];
	}

	bool findWay(Vertex current_vertex)//连通块,查看是否有解
	{
		if (DFN[current_vertex] != DFN[0])	return DFN[current_vertex];
		if (current_vertex == belong[end_vertex])
		{
			if (f[current_vertex] == f[belong[end_vertex]])	
			{
				return DFN[current_vertex] = true;
			}
			return false;
			//如果到达最重点,并且最重点能遍历的情况,和当前情况相同则为true
		}
		for (int i = 0; i != new_g[current_vertex].size(); ++ i)
		{
			Vertex will_vertex = new_g[current_vertex][i];
			if (current_vertex == will_vertex)	continue;//自己到自己就有环了。。不能这样
//			cout << current_vertex <<" " << will_vertex << endl;
			if (f[will_vertex] == (f[current_vertex] ^ f_self[current_vertex]))
			{
				if (findWay(will_vertex))	
				{
					return DFN[current_vertex] = true;
				}
			}
		}
		return DFN[current_vertex] = false;
	}

	bool check(Vertex current_vertex)//判断当前是否合法
	{
		//if (current_vertex == 4)	cout<<"!!!!!"< new_g[max_vertex_num]; //缩点后的新图,路径不包含非法点
};//起点和终点都是1 需要后来修改



map.h


#include "preInclude.h"

class Map
{

	public:
	vector g[max_vertex_num]; //邻接表
	unsigned short total_vertex; //最大的顶点标号,所有点的标号为1~total_vertex, 前面1~total_importan_vertex为重要点,其中1为起点,total_importan_vertex为终点
	unsigned short total_importan_vertex; //全部重要点的数量
	Vertex start_vertex; //起点标号。  一般为1
	Vertex end_vertex;   //终点标号, 一边为重要点的总数。


	void setTotalVertex(short total_vertex) //修改最大顶点标号
	{
		this -> total_vertex = total_vertex;
	}

	inline void setTotalImportanVertex(unsigned short total_importan_vertex) //修改重要的点最大点标号
	{
		this -> total_importan_vertex = total_importan_vertex;
	}

	inline void insert(Vertex arg0, Vertex arg1, unsigned short distance, unsigned short edge_num)
		//arg0 -> arg1 距离是distance ,边的标号是edge_num
	{
		if (this -> distance[arg0][arg1] > distance)
		{
			g[arg0].push_back(arg1);
			this -> distance[arg0][arg1] = distance;
			this -> edge_num[arg0][arg1] = edge_num;		
		}else
		{
			//do nothing	
		}
	}

	inline void setStartVertex(Vertex start_vertex)//修改起点标号
	{
		this -> start_vertex = start_vertex;
	}

	inline void setEndVertex(Vertex end_vertex)//修改终点标号
	{
		this -> end_vertex = end_vertex;
	}

	inline bool isConnected(Vertex arg0, Vertex arg1) //判断arg0和arg1是否连通
	{
		return edge_num[arg0][arg1] != null_distance;
	}

	inline unsigned short getDistance(Vertex arg0, Vertex arg1)// arg0->arg1的距离
	{
		return distance[arg0][arg1];
	}
	inline unsigned short getEdgeNum(Vertex arg0, Vertex arg1)//得到arg0->arg1的边
	{
		return edge_num[arg0][arg1];
	
	}


	Map(Vertex start, Vertex end):
		start_vertex(start),end_vertex(end),
		null_edge_num(56789),null_distance(56789) //构造函数,清空所有的变量
	{
		total_vertex = 0; //所有的顶点的数量为0,
		for (int i = 0; i != max_vertex_num; i ++)
		{
			g[i].reserve(10);
			for (int j = 0; j != max_vertex_num; j ++)
			{
				distance[i][j] = null_distance;
				edge_num[i][j] = null_edge_num;
			}
		}
	}

	private:
	unsigned short distance[max_vertex_num][max_vertex_num]; //距离矩阵
	unsigned short edge_num[max_vertex_num][max_vertex_num]; //边标号矩阵,只记录最小的边标号
	const unsigned short null_edge_num;
	const unsigned short null_distance;
};



preinclude.h


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int max_vertex_num = 610;
typedef unsigned short StatusVertex;
typedef unsigned short Vertex;
typedef bitset BitSetMap;
typedef unsigned short Evaluation;
typedef unsigned long long ImportantMap;//二进制表示一个被遍历过的重要的点的信息,如果没遍历到就-1

a0001.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int max_vertex_num = 610;
const int null_num = 56789;

typedef unsigned short StatusVertex;
typedef unsigned short Vertex;
typedef bitset BitSetMap;
typedef unsigned short Evaluation;
typedef unsigned long long ImportantMap;//二进制表示一个被遍历过的重要的点的信息,如果没遍历到就-1
bool is_important_vertex[max_vertex_num]={0}; //is_important_vertex[i]==true表示i是否是重要点


class Status
{
	public:
	inline BitSetMap getBitSetMap() //返回当前地图
	{
		return traversed_map;
	}
	inline Vertex getCurrentVertex()//返回当前地图所停留的顶点
	{
		return current_vertex;
	}
	inline long getEvaluation() //返回估价值
	{
		return evaluation;
	}
	inline bool operator < (Status arg0)	const
	{
		return evaluation < arg0.evaluation;
	}
	inline void setEvaluation(unsigned short evaluation)
	{
		this -> evaluation = evaluation;
	}
	inline bool isVisited(Vertex arg0)//arg0是否被访问过了
	{
		return traversed_map[arg0];
	}
	inline bool isAccessible(Vertex arg0)//arg0是否可以访问
	{
		return traversed_map[arg0] == 0;
	}

	Status()
	{
		current_ans = 0;
		traversed_map =0;
		evaluation =0;
		current_vertex = 0;
		traversed_important_vertexs = 0;
		traversed_all_vertexs = 0;
	}

	private:
	BitSetMap	traversed_map;   //保存整个地图的状态。 00001表示1号点被访问过了,00011 表示1,2都被访问过了。
	Vertex current_vertex;  //当前状态停留的顶点
	unsigned short evaluation;  //整个状态的估价值
	unsigned short traversed_all_vertexs; //所有遍历过的点的数量
	unsigned short traversed_important_vertexs; //所有被遍历过的重要点的数量
	unsigned short current_ans; //当前状态距离起点的距离
};


class RoadStatus
{
	public:
	bool isLegalSolution() //这个状态是否合法,是否存在路径到终点
	{
		return is_legal_solution;
	}
	bool setLegalSolution(bool flag)
	{
		is_legal_solution = flag;
	}
	
	private:
	bool is_legal_solution;
};

class Map
{

	public:
	vector g[max_vertex_num]; //邻接表
	unsigned short total_vertex; //最大的顶点标号,所有点的标号为1~total_vertex, 前面1~total_importan_vertex为重要点,其中1为起点,total_importan_vertex为终点
	unsigned short total_importan_vertex;
	Vertex start_vertex;
	Vertex end_vertex;


	void setTotalVertex(short total_vertex) //修改最大顶点标号
	{
		this -> total_vertex = total_vertex;
	}

	inline void setTotalImportanVertex(unsigned short total_importan_vertex) //修改重要的点最大点标号
	{
		this -> total_importan_vertex = total_importan_vertex;
	}

	inline void insert(Vertex arg0, Vertex arg1, unsigned short distance, unsigned short edge_num)
		//arg0 -> arg1 距离是distance ,边的标号是edge_num
	{
		if (this -> distance[arg0][arg1] > distance)
		{
			g[arg0].push_back(arg1);
			this -> distance[arg0][arg1] = distance;
			this -> edge_num[arg0][arg1] = edge_num;		
		}else
		{
			//do nothing	
		}
	}

	inline void setStartVertex(Vertex start_vertex)
	{
		this -> start_vertex = start_vertex;
	}

	inline void setEndVertex(Vertex end_vertex)
	{
		this -> end_vertex = end_vertex;
	}

	inline bool isConnected(Vertex arg0, Vertex arg1) //判断arg0和arg1是否连通
	{
	//	return edge_num[arg0][arg1] != null_distance;
	}

	inline unsigned short getDistance(Vertex arg0, Vertex arg1)
	{
		return distance[arg0][arg1];
	}


	Map(Vertex start, Vertex end):
		start_vertex(start),end_vertex(end),
		null_edge_num(56789),null_distance(56789) //构造函数,清空所有的变量
	{
		total_vertex = 0; //所有的顶点的数量为0,
		for (int i = 0; i != max_vertex_num; i ++)
		{
			g[i].reserve(10);
			for (int j = 0; j != max_vertex_num; j ++)
			{
				distance[i][j] = null_distance;
				edge_num[i][j] = null_edge_num;
			}
		}
	}
	

	private:
	unsigned short distance[max_vertex_num][max_vertex_num]; //距离矩阵
	unsigned short edge_num[max_vertex_num][max_vertex_num]; //边标号矩阵,只记录最小的边标号
	const unsigned short null_edge_num;
	const unsigned short null_distance;
};



class CheckMap:public Map  //生成一个Check变量,来完成所有的check操作
{
	public:
		/*
	CheckMap():Map()//初始化的时候,先调用Map初始化一下
	{
		clear();	
	}*/
	//CheckMap(){}

	CheckMap(Vertex start, Vertex end):Map(start, end)
	{
		clear();
	}	

	void clear() //清理tarjan和BFS运算所需要的数组元素
	{
		memset(DFN, 0, sizeof(DFN));
		memset(LOW, 0, sizeof(LOW));
		memset(instack, 0, sizeof(instack));
		memset(my_stack, 0, sizeof(my_stack));
		memset(f, 0, sizeof(f));
		memset(belong, 0, sizeof(belong));
		memset(belong_vertex_evaluation, 2, sizeof(belong_vertex_evaluation)); //数组清最大值
		memset(f_vis, false, sizeof(f_vis));//点是否被访问过,每个点只会被访问一次。(讲道理是这样)
		Stop = din = count = 0;
		total_evaluation_valve = 0; //估价清0
	}

	
	void tarjan(Vertex current_vertex)
	{
		LOW[current_vertex] = DFN[current_vertex] = ++ din;
		my_stack[++ Stop] = current_vertex;
		instack[current_vertex] = true;
		for (int i = 0; i != g[current_vertex].size(); ++ i)
		{
			int will_vertex = g[current_vertex][i];
			if (map_status.isVisited(will_vertex))	continue;//这个点已经在地图中被移除了
			if (!DFN[will_vertex])
			{
				tarjan(will_vertex);
				LOW[current_vertex] = min(LOW[current_vertex], LOW[will_vertex]);
			}
			else if (instack[will_vertex])	LOW[current_vertex] = min(LOW[current_vertex], DFN[will_vertex]);
		}
		if (LOW[current_vertex] == DFN[current_vertex])
		{
			int tmp;
			++count;
			do
			{
				tmp = my_stack[Stop --];
				instack[tmp] = false;
				belong[tmp] = count;
				if (tmp <= total_importan_vertex)//属于重要点的范畴
				{
					f[count] |= 1 << (tmp - 1); //f[count]这个连通块多了一些元素
				}
			}while (tmp != current_vertex);
		}
	}

	StatusVertex evaluationVertexLiantong(Vertex current_vertex)
	{
		unsigned short lei = belong[current_vertex]; //只能走这个种类的点
		DFN[current_vertex] = true; //访问标记
		//DFN[i]
		for (int i = 0; i != g[current_vertex].size(); i ++ )
		{
			Vertex will_vertex = g[current_vertex][i];
			if (belong[will_vertex] != lei || current_status.isVisited(will_vertex))	continue;
			total_evaluation_valve += getDistance(current_vertex, will_vertex);
			evaluationVertexLiantong(will_vertex);
		}
	
	}

	//版本0.01的getF,看看能不能成功
	ImportantMap getF(Vertex current_vertex)
	{

		if (f_vis[current_vertex] == true)	return f[current_vertex];
		f_vis[current_vertex] = true;	//访问标记
		if (current_vertex == end_vertex)//如果已经到了end_vertex,那么显然不能走动了
		{
			return f[belong[end_vertex]];
		}
		for (int i = 0; i != g[current_vertex].size(); ++ i)
		{
			f[current_vertex] |= getF(g[current_vertex][i]);
		}
		return f[current_vertex];
	}

	bool findWay(Vertex current_vertex)//连通块,查看是否有解
	{
		if (current_vertex == end_vertex)
		{
			if (f[current_vertex] == f[belong[end_vertex]])	return true;
			//如果到达最重点,并且最重点能遍历的情况,和当前情况相同则为true
		}
		for (int i = 0; i != new_g[current_vertex].size(); ++ i)
		{
			Vertex will_vertex = new_g[current_vertex][i];
			if (f[will_vertex] == (f[current_vertex] ^ f_self[current_vertex]))
			{
				if (findWay(will_vertex))	return true;
			}
		}
		return false;
	}

	RoadStatus check(Status current_status)//当前路径状态
	{
		this -> current_status = current_status;
		RoadStatus check_ret;
		clear(); //先清空所有数组元素
		Vertex current_vertex = current_status.getCurrentVertex();//得到当前顶点

		for (int i = 0; i <= total_vertex; i ++)
			if (current_status.isVisited(i) &&  !DFN[i])	tarjan(i);//缩点
		memmove(f_self, f, sizeof(f_self)); //f_self全部是都是每个点自己的状态

		for (int i = 0; i <= total_vertex; i ++)//重新构图
		{
			g[i].clear();
			for (int j = 0; j != g[i].size(); ++ j)
			{
				if (map_status.isVisited(g[i][j]))	continue; 
				//新构的图,不包含非法路径,因为垃圾点直接就不在图里 
				new_g[belong[i]].push_back(belong[g[i][j]]);
				belong_vertex_evaluation[belong[g[i][j]]] =    //更新每个连通块入度最小值
					min(belong_vertex_evaluation[belong[g[i][j]]], getDistance(belong[i], belong[g[i][j]]));
				//belong[i] - > belong[g[i][j]]
			}
		}


		getF(belong[current_vertex]);//做一个DP,得到f数组



		check_ret.setLegalSolution(findWay(belong[current_vertex]));
		if (!check_ret.isLegalSolution())	return check_ret; //非法解,退出

		/*开始估价每个连通块入度的总权重*/
		for (int i = 1; i <= count; ++ i)	
		{
			if (belong_vertex_evaluation[i] == belong_vertex_evaluation[0])	continue; //连通块入度为0,就直接continue
			total_evaluation_valve += belong_vertex_evaluation[i];//每个状态的入度增加
		}

		/*开始对每个连通块的权重进行估价*/
		memset(f_vis, false, sizeof(f_vis));//这个访问标记数组又要用了,是否访问表示连通块是否访问过
		memset(DFN, false, sizeof(DFN)); // dfn[i]现在为某个点是否访问过了
		for (int i = 1; i <= total_vertex; ++ i)
		{
			if (current_status.isAccessible(i) || f_vis[belong[i]])	continue;
			f_vis[belong[i]] = true;
			evaluationVertexLiantong(i);
			// belong[i]   i所属连通块
		}
	}


	private:
	Status current_status; //当前路径状态
	unsigned short DFN[max_vertex_num];  //时间戳
	unsigned short LOW[max_vertex_num]; //最早追溯到的时间戳
	bool instack[max_vertex_num]; // 顶点是否属于栈
	unsigned short my_stack[max_vertex_num]; //手写的一个简单的栈
	unsigned short belong[max_vertex_num]; //原来每个点,所属的连通块
	unsigned short Stop, din, count;//栈顶编号0~?, 时间戳编号1~?, 缩点后,每个连通块的编号1~?
	bool f_vis[max_vertex_num];
	unsigned short belong_vertex_evaluation[max_vertex_num]; //每个连通块入度最小的值
	ImportantMap f_self[max_vertex_num]; //f_self[i]表示i这个连通块里自己所拥有的重要的点
	ImportantMap f[max_vertex_num];//f[i]表示i后继能到的点
	vector new_g[max_vertex_num]; //缩点后的新图,路径不包含非法点
	unsigned short total_evaluation_valve; // 计算状态的估价
	Status map_status; //传递过来处理的map状态
}check(1, 1);//起点和终点都是1,需要后来修改



int getnum()
{
	return (rand() % 10) + 1;
}

int main()
{
	freopen("input.txt", "r", stdin);
	int n, m;
	cin >> n >> m;
	//srand(100);
	for (int i = 0; i != m; ++ i)
	{
		int a, b;
		cin >> a >> b;
		check.insert(i, a, b, 1); //随机给定一个权重
	}
	int zhongyaodian;
	cin >> zhongyaodian;
	check.setEndVertex(zhongyaodian);
	return 0;
}


check_dag.cpp

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;


int n, m;//n个点,m个边
vectorg[5000];
int zhongyao[5000], zhongyaodian;
int mp[5000]={0}; //是否是重要点

#define LL long long
int vis[5000] ={0}; //在dfs中是否被访问过
LL f[5000]={0}; //f[i]表示i这个节点,的根节点里,能到达的【重要节点】的数量(如果i是重要节点,那么f[i]的值也包含自己)。
int pre[5000];//记录路径

void insert(int a, int b)
{
	g[a].push_back(b);
}

void init()
{
	cin >> n >> m;
	for (int i = 1; i <= m; ++ i)
	{
		int a, b;
		cin >> a >> b ;
		insert(a, b);
	}
	cin >> zhongyaodian ;
	for (int i = 1; i <= zhongyaodian; ++ i)
	{
		int p;
		cin >> p;
		mp[p] = true;
	}
	memset(f, -1, sizeof(f));
	memset(pre, 0, sizeof(pre));
}

#define wei(k) (1LL<<(k-1))

LL dfs(int now) //得出上述的f数组
{
	if (f[now] != -1)	return f[now];
	if (now == n)	
	{
		return f[now] = wei(n);
	}
	if (mp[now])	f[now] = wei(now);
	else f[now] = 0;
	for (int i = 0; i != g[now].size(); ++ i)
	{
		int will = g[now][i];
		f[now] |= dfs(will);
	}
	return f[now];
}

int check(int now)
{
	if (now == n)
	{
		if (f[now] == (wei(n)))	return 1;
	}
	for (int i = 0; i != g[now].size(); ++ i)
	{
		int will = g[now][i];
		if (mp[now])//如果自己是重要点
		{
			if ( (f[will] | (wei(now))) == f[now])	
			{
				pre[will] = now;
				if (check(will))	return 1;
			}
		}else
		{
			if (f[will] == f[now])//总不能丢掉一些一定经过的节点吧?
			{
				pre[will]=now;
			//	if (will==8)	cout<<"!!!!!!!!!!!!!!!!!!"<


你可能感兴趣的:(水)