Mining Your Own Business
来源:互联网 发布:网络玄幻小说合集目录 编辑:程序博客网 时间:2024/05/16 17:52
题目链接
- 题意:
给定一个无向连通图,选择一些特殊点,当图中任意一个点(也有可能是特殊点)被删去的时候,其他点至少能到达一个特殊点
输入:n表示边数;每行两个数表示一条边(从1开始)
输出:需要的最少的特殊点和总的方案数 - 分析:
首先,如果没有删去点,所有的点都可以到达任意一个特殊点(连通)。主要是分析连通性,所以从割点入手(不要忘了可以删特殊点)
显然,特殊点如果选割点的话是不划算的。
对于每一个割点个数为1的图,如果图中没有特殊点,那么至少删去割点,这个图就不能到达特殊点,所以这样的图必须有一个特殊点
之后,对于任意一个图,如果删除图中的点,那么不影响(不影响连通性);如果删除这个图的一个割点,那么总有一个割点为1的图与之连通
(个人理解)将所有的点双连通分量缩成一个点,割点变成连接两个点双连通分量的边,那么生成的图是无向无环的图(树)
那么,删去的点认为就是一个双连通分量(即生成的图中的一个点),删去的边认为是删去了一个割点
问题就变成了在树中删去一个点或者边,使得所有的点都能到达特殊点,也就是所有的根和叶子为特殊点 - 特殊情况:当只有一个连通分量时候需要单独考虑,即两个特殊点
- 重点:
选取特殊点的位置不能是割点
特殊点必选在割点数量为1的图中
考虑到没有割点的图的情况
//无向图的双连通分量//每次调用前手动清空vector<int> G//使用时只更新G完成构图//bcc_cnt从1开始计数//pre[]表示点在DFS树中的先序时间戳//iscut[]表示点是否为割点//bccno[]表示点所在的双连通分量编号//bcc_cnt表示双连通分量个数//vector<int> G保存每个点相邻的下一个点序号//vector<int> bcc保存每个双连通分量的点集,算法运行过程动态清空//stack<Edge> S是算法用到的栈const int MAXV = 51000;const int MAXE = 51000;int pre[MAXV], iscut[MAXV], bccno[MAXV], dfs_clock, bcc_cnt; // 割顶的bccno无意义struct Edge{ int u, v;};vector<int> G[MAXV], bcc[MAXV];stack<Edge> S;int dfs(int u, int fa){ int lowu = pre[u] = ++dfs_clock; int child = 0; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; Edge e = (Edge){u, v}; if(!pre[v]) // 没有访问过v { S.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); // 用后代的low函数更新自己 if(lowv >= pre[u]) { iscut[u] = true; bcc_cnt++; bcc[bcc_cnt].clear(); for(;;) { Edge x = S.top(); S.pop(); if(bccno[x.u] != bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt; } if(bccno[x.v] != bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt; } if(x.u == u && x.v == v) break; } } } else if(pre[v] < pre[u] && v != fa) { S.push(e); lowu = min(lowu, pre[v]); // 用反向边更新自己 } } if(fa < 0 && child == 1) iscut[u] = 0; return lowu;}void find_bcc(int n){ // 调用结束后S保证为空,所以不用清空 memset(pre, 0, sizeof(pre)); memset(iscut, 0, sizeof(iscut)); memset(bccno, 0, sizeof(bccno)); dfs_clock = bcc_cnt = 0; for(int i = 0; i < n; i++) if(!pre[i]) dfs(i, -1);};int main(){// freopen("in.txt", "r", stdin); int n, a, b, kase = 1; while (~RI(n) && n) { REP(i, MAXV) G[i].clear(); int Max = 0; REP(i, n) { RII(a, b); a--; b--; Max = max(Max, max(a, b)); G[a].push_back(b); G[b].push_back(a); } find_bcc(Max); LL ans = 1, cnt = 0; if (bcc_cnt == 1) { LL m = bcc[1].size(); ans = m * (m - 1) / 2; cnt = 2; } else { FE(i, 1, bcc_cnt) { int tcnt = 0; REP(j, bcc[i].size()) { if (iscut[bcc[i][j]]) tcnt++; } if (tcnt == 1) { ans *= (bcc[i].size() - 1); cnt++; } } } printf("Case %d: ", kase++); cout << cnt << ' ' << ans << endl; } return 0;}
12 0
- Mining Your Own Business
- LA5135 Mining Your Own Business
- La5135 Mining your own Business
- UVALive - 5135 Mining Your Own Business
- LA 5135 Mining Your Own Business
- hdu 3844 Mining Your Own Business
- HDU-3844-Mining Your Own Business
- UVALive - 5135 Mining Your Own Business
- UVALive5135 - Mining Your Own Business(BCC)
- uvaoj 1108 - Mining Your Own Business
- UVA 1108 - Mining Your Own Business
- UVA1108 HDU3844 Mining Your Own Business
- Mining Your Own Business(点双联通)
- Mining Your Own Business LA 5135
- UVALive 5135 Mining Your Own Business(BCC、割顶)
- UVA 1108 - Mining Your Own Business(双连通分量)
- UVALive 5135 HDU 3844 Mining Your Own Business
- UVALive 5135 - Mining Your Own Business(点双连通)
- 第三周作业-冒泡排序与归并排序
- Android中PackageManager学习笔记(1)-ApplicationInfo
- Latent Semantic Analysis (LSA) Tutorial 潜语义分析LSA介绍 二
- shell脚本配置环境变量时 source XXX.sh与 ./XXX.sh的区别
- 排序 之 堆
- Mining Your Own Business
- POJ 1787 Charlie's Change / 完全背包
- -------------------------android-带进度条的系统通知栏消息
- Android中 像素单位详解
- DataSet更新到数据库总结
- 优秀的程序员和一般的程序员差别在哪?
- 关于typedef的用法总结
- 单片机播放WAV格式音频的理解
- 设计模式学习(六)——命令模式