Codeforces Round #364 (Div. 2) F. Break Up(割边)
来源:互联网 发布:软件license管理器 编辑:程序博客网 时间:2024/06/11 04:40
参考题解:http://codeforces.com/contest/701/problem/F
感觉这题思路并不难,但是编码不太容易。
思路:
首先判断图的连通性,看S和T是否在同一个连通块里面,如果不在的话,就直接输出结果。如果在一个连通块里面的话,再进行后续的判断。
当S和T连通的时候,求出两点间的一条路径,因为最多只能删除删除两条边,如果有解的话,肯定有一条边在这个路径里。如果S和T只有一条路径,那肯定就是这一条路径,如果S和T有两条不相交的路径,肯定每个路径要删除一条边。如果S和T之间超过两条不相交路径,肯定无解了。
- 先枚举找到这条路径的每条边,如果存在割边的话,就更新答案,枚举完路径上的边之后。然后再枚举删除这条路径的每条边,然后再找一条S和T之间的路径,看这条路径上有没有割边,有的话,就更新答案。
#include <bits/stdc++.h>using namespace std;const int MAXN = 1111;const int MAXM = 66666;const int INF = 2e9+10;int Dfn[MAXN],Low[MAXN];struct Edge{ int to,next,w,id;}edge[MAXM];int head[MAXN];bool cut[MAXM],vis[MAXN],isBridge[MAXM];int s,t,n,m,cnt,tot;vector<int> path,ans,opath;void init(){ memset(head,-1,sizeof(head)); tot = 1;}void addedge(int u, int v, int w, int id){ edge[tot].to = v; edge[tot].w = w; edge[tot].id = id; edge[tot].next= head[u]; head[u] = tot++;}bool dfs(int u, int pre){ if(u == t) return true; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; int id = edge[i].id; if(vis[v] || cut[id] || id == pre) continue; vis[v] = true; if(dfs(v,id)) { path.push_back(id); return true; } } return false;}bool findPath(){ memset(vis,false,sizeof(vis)); path.clear(); vis[s] = true; return dfs(s,0);}void Tarjan(int u, int pre){ Dfn[u] = Low[u] = cnt++; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; int id = edge[i].id; if(cut[id]) continue; if(!Dfn[v]) { Tarjan(v,id); Low[u] = min(Low[u],Low[v]); if(Dfn[u] < Low[v]) isBridge[id] = true; } else if(id != pre) Low[u] = min(Low[u],Dfn[v]); }}void findBridge(){ memset(Dfn,0,sizeof(Dfn)); memset(Low,0,sizeof(Low)); memset(isBridge,false,sizeof(isBridge)); cnt = 0; for(int i = 1; i <= n; ++i) if(!Dfn[i]) Tarjan(i,0);}void solve(){ memset(cut,false,sizeof(cut)); int res = INF; ans.clear(); //dfs判定图的连通性,顺便记录s-t的路径 if(!findPath()) { puts("0\n0"); return; } //求割边 findBridge(); int nb; //如果s-t的路径上有割边,去掉这个割边就可以使s-t不连通 for(int i = 0; i < path.size(); ++i) { nb = path[i]; if(isBridge[nb] && edge[nb*2].w <= res) { ans.clear(); ans.push_back(nb); res = edge[nb*2].w; } } opath.clear(); opath.insert(opath.begin(),path.begin(),path.end()); //枚举刚才找到的那条路径的每条边,删除这条边后再找桥 //即找两条边的最小花费 for(int i = 0; i < opath.size(); ++i) { nb = opath[i]; cut[nb] = true; if(!findPath()) { cut[nb] = false; continue; } findBridge(); for(int j = 0; j < path.size(); ++j) { int onb = path[j]; if(isBridge[onb] && (edge[onb*2].w + edge[nb*2].w) <= res) { ans.clear(); ans.push_back(nb); ans.push_back(onb); res = edge[onb*2].w + edge[nb*2].w; } } cut[nb] = false; } //如果一条边都没找到,就无解喽 if(ans.size()) { printf("%d\n%d\n",res,ans.size()); for(int x : ans) printf("%d ",x); } else puts("-1");}int main(){ init(); int u,v,w; scanf("%d %d",&n,&m); scanf("%d %d",&s,&t); for(int i = 1; i <= m; ++i) { scanf("%d %d %d",&u,&v,&w); addedge(u,v,w,i); addedge(v,u,w,i); } solve(); return 0;}
阅读全文
0 0
- Codeforces Round #364 (Div. 2) F. Break Up(割边)
- 【Codeforces Round 364 (Div 2)F】【暴力 双连通分量求桥】Break Up n点m边最多割2边最小成本使得S与T不联通
- Codeforces Round #364 F Break Up
- Codeforces Round #364 (Div. 1) C. Break Up (桥)
- Codeforces Round #364 (Div. 1) C.Break Up
- B. Ohana Cleans Up(Codeforces Round #309 (Div. 2))
- Codeforces Round #376 (Div. 2)F(前缀和,模拟)
- Codeforces Round #377 (Div. 2)(D.E.F)
- Codeforces Round #376 (Div. 2)F. Video Cards(乱搞)
- Codeforces Round #442 (Div. 2) 题解(877A~F)
- Codeforces Round #277.5 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- Codeforces Round #279 (Div. 2) B F
- Codeforces Round #277.5 (Div. 2)F题
- Codeforces Round #322 (Div. 2) F
- Codeforces Round #377 (Div. 2) F
- Codeforces Round #386 (Div. 2) F
- ionic中实现从相册中选择图片并一次上传多张图片
- Hadoop Streaming框架学习(二)
- jquery live方法,解决jquery动态添加按钮无法触发点击事件的问题
- 使用新浪云SAE建立一个公网可访问的网页应用
- 第十一章 img特征 vertical-align cursor opactiy
- Codeforces Round #364 (Div. 2) F. Break Up(割边)
- 谁考了第k名
- 逻辑回归模型(Logistic Regression, LR)基础
- 双系统/虚拟机安装实践记录
- JZOJ 5398. 【NOIP2017提高A组模拟10.7】Adore
- 20171007离线赛总结
- 字典树Trie
- 第五周项目3 括号的匹配
- 软设之路2.1--软件过程