TC SRM 684 Div2 900pts
来源:互联网 发布:中央网络电视台 编辑:程序博客网 时间:2024/05/15 12:46
题意:
给定一个有向图,可能会有重边和自环。问是否会有一条路径使得图中每个点都至少被访问一次。
n≤50
解释:
其实这题并不难,因为数据范围较小,所以可以有很多方法暴力解决!
看了一下TC的官方题解,感觉学到了一波姿势!第一点 : 首先肯定是要缩点,一般是Tarjan咯!
题解是提供了一种N3 的缩点的方法:
用邻接矩阵表示这个图,然后 Floyd 处理出任意两个点是否可达。
然后就可以达到缩点的目的了!第二点:缩点后得到一个 DAG,然后判断是否可以一条路径覆盖所有的点,这个可以用 最小路径覆盖解决,也就是经典的二分图匹配。
题解给出的是 topsort :
按拓扑排序的方法去选出路径上的每个点,最后判断一下选出的点的序列中相邻的两个点之间是否存在可达就行了!思考:这种方法确实可以去解决这种是否存在一条路径覆盖所有点的问题,而且效率是高于二分图匹配的,但是这种方法是否可以代替用二分图匹配去解决最小路径覆盖的问题呢?
也就是说,我们先按拓扑排序的方法得到选出的点的序列,然后判断这个序列中相邻的点
u,v ,是否满足reach[u][v]==1 ,也就是是否可达,如果不满足就ans++ ,这样得到最终的最小路径覆盖!这样的做法是否正确呢?
代码:
string check(vector<int> z0, vector<int> z1){ // create the graph from input, adjacency matrix: int n = z0.size(); vector< vector<int> > a(n, vector<int>(n,0) ); for (int i = 0; i < n; i++) { a[i][z0[i]] = 1; a[i][z1[i]] = 1; } // Floyd-Warshall to quickly get which vertices are reachable from which starting points: auto d = a; for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { d[i][j] = (d[i][j] || (d[i][k] && d[k][j]) ); } } } // if a vertex u is reachable from vertex v and vice versa, then they // belong to the same SCC, use that information to build a SCC graph: vector<int> node_compo(n, -1); int t = 0; for (int i = 0; i < n; i++) { if (node_compo[i] == -1) { node_compo[i] = t++; for (int j = 0; j < n; j++) { if ( d[i][j] && d[j][i] ) { node_compo[j] = node_compo[i]; } } } } vector< set<int> > g(t) , rg(t); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int u = node_compo[i]; int v = node_compo[j]; if ( (u != v) && a[i][j] ) { g[u].insert(v); rg[v].insert(u); } } } // topsort the SCC graph: vector<int> top_sort(t); vector<bool> added(t, false); for (int i = 0; i < t; i++) { int pick = -1; for (int j = 0; j < t; j++) { if ( ! added[j] ) { int cnt = 0; for (int k : rg[j]) { if ( !added[k] ) { cnt++; } } if (cnt == 0) { pick = j; } } } if ( pick == -1) { return "Does not exist"; } else { top_sort[i] = pick; added[pick] = true; cout << "["; for (int i = 0; i < n; i++) { if (node_compo[i] == pick) { cout << i << " "; } } cout << "]" << endl; } } if (top_sort[0] != 0) { return "Does not exist"; } // check the path: for (int i = 1; i < t; i++) { if ( g[ top_sort[i-1] ].count( top_sort[i]) == 0) { return "Does not exist"; } } return "Exists";}
0 0
- TC SRM 684 Div2 900pts
- TC SRM 683 Div2(1000pts)
- TC SRM 684 Div2
- TC SRM 152 DIV2
- TC SRM 540 DIV2
- TC SRM 548 DIV2
- TC SRM 400 DIV2
- TC SRM 549 DIV2
- TC SRM 552 DIV2
- TC SRM 553 DIV2
- TC SRM 571 div2
- TC SRM 604 div2
- TC SRM 607 DIV2
- TC SRM div2 500
- TC SRM 551 div2 题解
- TC SRM 557 DIV2 1000
- [TC] SRM 633 div2 250
- TC SRM 395 Div2 250
- AlphaGo开源代码
- 【翻译自mos文章】在RHEL7/OL7上安装Oracle 12.1.0.2的服务器端或者客户端时,报需要"compat-libstdc++"包
- 3.redis内存占用飙升
- 6.继承与面向对象设计
- POJ_P1741 Tree(树上点分治)
- TC SRM 684 Div2 900pts
- android gradle plugin 1.3.0 以上使用 public.xml 固定 id
- 你不知道的JavaScript--Item34 大白话讲解Promise
- MFC对话框-DoDataExchange()函数使用
- 01背包
- Cocos2d-x 2048游戏教程 第一部分
- 动态规划 HDU 1466 计算直线的交点数
- Oracle简单使用【一】
- 4.redis内存使用优化