枚举+求桥 Codeforces701F Break Up
来源:互联网 发布:小米手环数据修改攻略 编辑:程序博客网 时间:2024/04/26 06:31
传送门:点击打开链接
题意:最多删掉2条边,使得无向图中s到t不连通。点数<=1e3,边数<=3e4
思路:我们先求一条s到t的任意路径。
我们很容易就能证明,如果存在这样的2条边,或者说只需要删一条边就能让他们两个不连通,那么必然是在s到t的一条路径上。
所以,我们首先求出任意一条s到t的路径。
然后枚举这条路径上的边,最多也只有n-1条。
枚举完后,把这条边删了,求桥,而且这个桥必须要满足,S和T分别在桥的两端。
我们可以这样来判断这种桥是否存在。
首先我们从S开始tarjan,当我们枚举u的一条边e,另一个点是v时候,发现DFN[u]<Low[v],说明这条边是桥,然后我们又发现DFN[v]<=DFN[T],T表示终点,此时就说明,T和v在桥的相同一侧,也就是说T和S就恰好分别在桥的两边了。
找到这样的桥后,再和我们之前枚举删除的边的权值加起来组合更新答案即可。
我通常对于这种方案比较复杂的,写一个Ans的结构体,之后维护方案感觉方便的多
#include <map>#include <set>#include <cmath>#include <ctime>#include <stack>#include <queue>#include <cstdio>#include <cctype>#include <bitset>#include <string>#include <vector>#include <cstring>#include <iostream>#include <algorithm>#include <functional>#define fuck(x) cout<<"["<<x<<"]";#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("input.txt","w+",stdout);//#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long LL;typedef pair<int, int> PII;const int MX = 1e3 + 5;const int INF = 0x3f3f3f3f;struct Edge { int u, v, nxt, cost;} E[200005];int n, m, S, T, dfn, del, ans1, ansid;int Head[MX], erear;int DFN[MX], Low[MX];void edge_init() { erear = 0; memset(Head, -1, sizeof(Head));}void edge_add(int u, int v, int cost) { E[erear].u = u; E[erear].v = v; E[erear].cost = cost; E[erear].nxt = Head[u]; Head[u] = erear++;}inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } return x;}class Path {public: bool vis[MX]; int S[MX], E[MX], fa[MX], sz; void solve() { sz = 0; memset(vis, 0, sizeof(vis)); queue<int>Q; Q.push(::S); vis[::S] = 1; fa[::S] = -1; bool ok = 0; int u, v; while(!Q.empty()) { u = Q.front(); Q.pop(); if(u == T) { ok = 1; break; } for(int i = Head[u]; ~i; i =::E[i].nxt) { v =::E[i].v; if(vis[v]) continue; Q.push(v); vis[v] = 1; fa[v] = u; E[v] = (i + 2) / 2; } } if(!ok) return; u = T; while(fa[u] != -1) { S[++sz] = E[u]; u = fa[u]; } }} path;struct Ans { int id[2]; int num, totcost; Ans() { num = 0; totcost = 2 * INF; } void print() { if(totcost == 2 * INF) printf("-1\n"); else { printf("%d\n%d\n", totcost, num); for(int i = 0; i < num; i++) printf("%d ", id[i]); } }};int P[MX];int find(int x) { return P[x] == x ? x : (P[x] = find(P[x]));}void tarjan(int u, int e) { Low[u] = DFN[u] = ++dfn; for(int i = Head[u]; ~i; i = E[i].nxt) { if((i + 2) / 2 == del) continue; int v = E[i].v; if(!DFN[v]) { tarjan(v, i | 1); Low[u] = min(Low[u], Low[v]); if(Low[v] > DFN[u] && DFN[v] <= DFN[T] && ans1 > E[i].cost) { ansid = (i + 2) / 2; ans1 = E[i].cost; } } else if((i | 1) != e && DFN[v] < DFN[u]) { Low[u] = min(Low[u], DFN[v]); } }}void find_bridge() { ans1 = INF; dfn = 0; memset(DFN, 0, sizeof(DFN)); tarjan(S, -1);}int main() { //FIN; edge_init(); scanf("%d%d", &n, &m); scanf("%d%d", &S, &T); for(int i = 1; i <= n; i++) P[i] = i; for(int i = 1; i <= m; i++) { int u = read(), v = read(), cost = read(); edge_add(u, v, cost); edge_add(v, u, cost); int p1 = find(u), p2 = find(v); P[p1] = p2; } if(find(S) != find(T)) { printf("0\n0\n"); return 0; } Ans ans; path.solve(); find_bridge(); if(ans1 != INF) { ans.num = 1; ans.totcost = ans1; ans.id[0] = ansid; } for(int i = 1; i <= path.sz; i++) { del = path.S[i]; //uck(del); find_bridge(); //printf("[%d,%d] %d\n", del, ansid, ans); if(ans1 != INF && ans1 + E[(del - 1) * 2].cost < ans.totcost) { ans.num = 2; ans.id[0] = ansid; ans.id[1] = del; ans.totcost = ans1 + E[(del - 1) * 2].cost; } } ans.print(); return 0;}
0 0
- 枚举+求桥 Codeforces701F Break Up
- Codeforces 700C Break Up tarjan求桥
- codeforces 700C. Break Up 枚举
- Codeforces Round #364 (Div. 1) C. Break Up (桥)
- poj1118Lining Up 暴力枚举
- POJ 1118 Lining Up(枚举)
- Codeforces700C Break Up(搜索+tarjan)
- Codeforces Round #364 F Break Up
- Warm up 【tarjan 求EBC+求桥+缩点+树的直径】
- HDU-3681 Prison Break (bfs + 二分枚举)
- 枚举法求迷宫
- 利用枚举,求坐标
- uva - 270 - Lining Up(枚举、排序)
- Time To Get Up(枚举)
- I won't give up, I won't break down
- I am going to break up with you
- 代码之破碎时刻(代码片断分析)(Break Up Time)
- Codeforces Round #364 (Div. 1) C.Break Up
- hdu 5730(分治FFT)
- poj3278 Catch That Cow
- POJ 1258Agri-Net
- [概率dp 矩阵乘法] poj 3744 Scout YYF I
- java-学习-自我规划
- 枚举+求桥 Codeforces701F Break Up
- POJ1995 Raising Modulo Numbers
- Codeforces Round #364 (Div. 2)E.Connecting Universities
- HDU 1052 Tian Ji -- The Horse Racing
- 重构
- mysql cluster (mysql 集群)安装配置方案
- 浅谈Java的final关键字
- mysql分区技术测试
- 矩阵论还真有用:图片缩放旋转