突然600多阅读我慌了。。感觉浪费大家赞了……
题目是http://codecraft.huawei.com/ 2016年初赛的题,类似TSP问题的那个……。
思路如下: 搜。
然后就傻乎乎搜炸了啊。。。
tarjan缩点后,DP剪枝去掉非法解(能去掉非常多的)。
结果依然是大数据出不了解。。。 所以我的方法非常烂啦
===================================
我们自以为很厉害的方法~实际上很垃圾,初赛20多分的样子,显然被刷啦~~~
但是毕竟做了。。代码保留一下就好了
往事不堪回首。。也不想读代码了。。直接看代码注释。。 这篇文章应该没人看吧…… 自己留纪念
#include "CheckMap.h" #include <queue> #include <ctime> 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 " <<final_ans<< endl; //cout <<"this program runs: "<< start/1000.0 - clock()/1000.0 << "ms" << endl; return 0; }
#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<<"!!!!!"<<endl; clear(); //先清空所有数组元素 for (int i = 1; i <= total_vertex; i ++) { if (!vis[i] && !DFN[i]) tarjan(i);//缩点 } for (int i = 1; i <= count; ++ i) new_g[i].clear(); for (int i = 1; i <= total_vertex; i ++)//重新构图,顶点标号从1~total_vertex开始 { if (vis[i]) continue;//出发点不合法 for (int j = 0; j != g[i].size(); ++ j) { if (vis[g[i][j]] || belong[i] == belong[j]) continue; new_g[belong[i]].push_back(belong[g[i][j]]); } } memmove(f_self, f, sizeof(f_self)); //f_self全部是都是每个点自己的状态 getF(belong[current_vertex]);//做一个DP,得到f数组 /*这个地方有一个优化! * 一开始预处理所有的子节点情况,如果不合法可以直接退出,得出情况 * 第一个点的后继,是否已经是全部未访问节点! */ memset(DFN, 120, sizeof(DFN)); //清理DFN数组,用来给findWay用 return findWay(belong[current_vertex]); //备忘: 是否用bool就可以完成check } private: 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 Stop, din, count;//栈顶编号0~?, 时间戳编号1~?, 缩点后,每个连通块的编号1~? bool f_vis[max_vertex_num]; ImportantMap f_self[max_vertex_num]; //f_self[i]表示i这个连通块里自己所拥有的重要的点 vector<Vertex> new_g[max_vertex_num]; //缩点后的新图,路径不包含非法点 };//起点和终点都是1 需要后来修改
#include "preInclude.h" class Map { public: vector<short> 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 <iostream> #include <cstdio> #include <ctime> #include <cstring> #include <bitset> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; const int max_vertex_num = 610; typedef unsigned short StatusVertex; typedef unsigned short Vertex; typedef bitset<max_vertex_num> BitSetMap; typedef unsigned short Evaluation; typedef unsigned long long ImportantMap;//二进制表示一个被遍历过的重要的点的信息,如果没遍历到就-1
#include <iostream> #include <cstdio> #include <ctime> #include <cstring> #include <bitset> #include <cstdlib> #include <vector> using namespace std; const int max_vertex_num = 610; const int null_num = 56789; typedef unsigned short StatusVertex; typedef unsigned short Vertex; typedef bitset<max_vertex_num> 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<short> 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<Vertex> 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 <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int n, m;//n个点,m个边 vector<int>g[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<<"!!!!!!!!!!!!!!!!!!"<<endl; if (check(will)) return 1; } } } return 0; } int main() { init(); dfs(1); cout << (check(1) ? "yes" : "no") << endl; return 0; }