LightOJ - 1429 Assassin`s Creed (II)(二分图)
2015-11-03 22:53
357 查看
题目大意:给你一张有向图,问这张有向图有多少个DAG
解题思路:因为会存在环,所以得先缩点
缩点完后,就可以进行二分图匹配了,DAG的数量就是最大独立集的数量了
这题卡了邻接表
解题思路:因为会存在环,所以得先缩点
缩点完后,就可以进行二分图匹配了,DAG的数量就是最大独立集的数量了
这题卡了邻接表
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int MAXNODE = 1010; const int MAXEDGE = 10010; struct Edge{ int u, v, next; Edge() {} Edge(int u, int v, int next):u(u), v(v), next(next) {} }E[MAXEDGE]; //head数组表示头指针,pre数组纪录的是时间戳,lowlink纪录当前节点及其后代所能连回的最早的祖先的时间戳,sccno纪录的是节点是属于哪个强连通分量的 //Stack数组模拟栈,num数组纪录的是每个强连通分量中有多少个节点 int head[MAXNODE], pre[MAXNODE], lowlink[MAXNODE], sccno[MAXNODE], Stack[MAXNODE]; //tot纪录的是边的数量,dfs_clock就是时间戳,top指向栈顶,scc_cnt纪录有多少个强连通分量 int tot, n, m, dfs_clock, top, scc_cnt, cas = 1, All; bool vis[MAXNODE]; int left[MAXNODE]; vector<int> V[MAXNODE]; vector<int> DAG[MAXNODE]; vector<int> G[MAXNODE]; void init() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { G[i].clear(); DAG[i].clear(); V[i].clear(); } int u, v; for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); G[u].push_back(v); } } void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock;//纪录当前节点的时间戳 Stack[++top] = u; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; //如果下一个节点没有访问过 if (!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); }//如果下一个节点已经被访问过了,且不属于任何一个连通分量 else if (!sccno[v]) lowlink[u] = min(lowlink[u], pre[v]); } int x; //满足强连通分量的要求,当前节点u为该强连通分量最早发现的节点 if (pre[u] == lowlink[u]) { scc_cnt++; while (1) { x = Stack[top--]; sccno[x] = scc_cnt; if (x == u) break; } } } bool dfs2(int u) { for (int i = 0; i < V[u].size(); i++) { int v = V[u][i]; if (vis[v]) continue; vis[v] = true; if (!left[v] || dfs2(left[v])) { left[v] = u; return true; } } return false; } void bfs(int cur) { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(cur); vis[cur] = true; while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if (vis[v]) continue; vis[v] = true; DAG[cur].push_back(v); Q.push(v); } } } void solve() { memset(pre, 0, sizeof(pre)); memset(sccno, 0, sizeof(sccno)); dfs_clock = top = scc_cnt = 0; for (int i = 1; i <= n; i++) bfs(i); for (int i = 1; i <= n; i++) if (!pre[i]) dfs(i); int u, v; for (int i = 1; i <= n; i++) { for (int j = 0; j < DAG[i].size(); j++) { u = sccno[i]; v = sccno[DAG[i][j]]; if (u == v) continue; V[u].push_back(v); } } int ans = 0; memset(left, 0, sizeof(left)); for (int i = 1; i <= scc_cnt; i++) { memset(vis, 0, sizeof(vis)); if (dfs2(i)) ans++; } printf("Case %d: %d\n", cas++, scc_cnt - ans); } int main() { int test; scanf("%d", &test); while (test--) { init(); solve(); } return 0; }
相关文章推荐
- HDU 5023 A Corrupt Mayor's Performance Art (线段树区间更新,入门详解)
- Leetcode Excel Sheet Column Number
- Criteria 外键匹配查询
- java面试--String详解
- Eclipse中的快捷键功能
- LightOJ - 1209 Strange Voting(二分图)
- 网络通信中字节序转换问题
- linux下core文件调试方法
- 巧用Systemtap注入延迟模拟IO设备抖动
- Code First Migrations更新数据库结构的具体步骤
- 听点古典
- lua几点注意和脚本操作gui文件
- shell类型与配置文件
- 声控开关电路原理图-门电路、限流电阻应用经典分析
- Oracle创建DBlink和Sysnonyms(同义词,表映射)的方法及常见问题处理
- Java中Static作用
- spacemacs快速入门
- 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)
- iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)
- 让Java代码跑得更快