[HDOJ4612]Warm up(双连通分量,缩点,树直径)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDOJ4612]Warm up(双连通分量,缩点,树直径)相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612

所有图论题都要往树上考虑

题意:给一张图,仅允许添加一条边,问能干掉的最多条桥有多少。

必须解决重边的问题,最后会说。

首先tarjan跑出所有的双连通分量和是桥的边还有桥的数量,这非常重要。接着缩点重新建图,然后两遍dfs找出两个在树上距离最远的点。我的想法就是把这条最长的链连成一个环,让它成为一个双连通分量,这样的效果是最好的。最后就是用桥的数量减去树直径再减一就得到了剩下的桥的数量了。求树直径的时候重用了dfn数组,不要以为是错的就好。

重边真的好烦人啊,我像处理离散化那样unique了一下,发现是不可行的。最终还是参考了bin神的方法,在边的结构体里加一个记号来标记这个边是不是重边,也就是出现重边的话,那这几条重边就不是桥啦。如果按照我之前的做法,重边会被删掉,所以桥的数量会增多,显然是不对的。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <algorithm>
 18 #include <iostream>
 19 #include <iomanip>
 20 #include <cstring>
 21 #include <climits>
 22 #include <complex>
 23 #include <fstream>
 24 #include <cassert>
 25 #include <cstdio>
 26 #include <bitset>
 27 #include <vector>
 28 #include <deque>
 29 #include <queue>
 30 #include <stack>
 31 #include <ctime>
 32 #include <set>
 33 #include <map>
 34 #include <cmath>
 35 using namespace std;
 36 #define fr first
 37 #define sc second
 38 #define cl clear
 39 #define BUG puts("here!!!")
 40 #define W(a) while(a--)
 41 #define pb(a) push_back(a)
 42 #define Rint(a) scanf("%d", &a)
 43 #define Rll(a) scanf("%lld", &a)
 44 #define Rs(a) scanf("%s", a)
 45 #define Cin(a) cin >> a
 46 #define FRead() freopen("in", "r", stdin)
 47 #define FWrite() freopen("out", "w", stdout)
 48 #define Rep(i, len) for(int i = 0; i < (len); i++)
 49 #define For(i, a, len) for(int i = (a); i < (len); i++)
 50 #define Cls(a) memset((a), 0, sizeof(a))
 51 #define Clr(a, x) memset((a), (x), sizeof(a))
 52 #define Full(a) memset((a), 0x7f7f, sizeof(a))
 53 #define lp p << 1
 54 #define rp p << 1 | 1
 55 #define pi 3.14159265359
 56 #define RT return
 57 typedef long long LL;
 58 typedef long double LD;
 59 typedef unsigned long long ULL;
 60 typedef pair<int, int> pii;
 61 typedef pair<string, int> psi;
 62 typedef map<string, int> msi;
 63 typedef vector<int> vi;
 64 typedef vector<LL> vl;
 65 typedef vector<vl> vvl;
 66 typedef vector<bool> vb;
 67 
 68 const int maxn = 200020;
 69 const int maxm = 1500000;
 70 
 71 typedef struct Edge {
 72     int u, v;
 73     int next;
 74     bool cut, r;
 75     Edge() { next = -1; cut = 0; }
 76 }Edge;
 77 
 78 typedef struct Tmp {
 79     int u, v;
 80     Tmp() {}
 81     Tmp(int uu, int vv) : u(uu), v(vv) {}
 82     bool operator==(Tmp p) { RT u == p.u && v == p.v; }
 83 }Tmp;
 84 
 85 int head[maxn], ecnt;
 86 int n, m;
 87 int bcnt, idx;
 88 int dfn[maxn], low[maxn];
 89 int stk[maxn], top;
 90 int belong[maxn];
 91 bool instk[maxn];
 92 Edge edge[maxm];
 93 Tmp tmp[maxm];
 94 vector<int> G[maxn];
 95 
 96 bool cmp(Tmp x, Tmp y) {
 97     if(x.u == y.u) RT x.v < y.v;
 98     RT x.u < y.u;
 99 }
100 
101 void init() {
102     memset(edge, 0, sizeof(edge));
103     memset(head, -1, sizeof(head));
104     memset(instk, 0, sizeof(instk));
105     memset(dfn, 0, sizeof(dfn));
106     memset(low, 0, sizeof(low));
107     memset(belong, 0, sizeof(belong));
108     ecnt = top = bcnt = idx = 0;
109 }
110 
111 void adde(int uu, int vv, bool p) {
112     edge[ecnt].u = uu;
113     edge[ecnt].v = vv;
114     edge[ecnt].cut = 0;
115     edge[ecnt].r = p;
116     edge[ecnt].next = head[uu];
117     head[uu] = ecnt++;
118 }
119 
120 void tarjan(int u, int p, int r) {
121     int v = u;
122     dfn[u] = low[u] = ++idx;
123     stk[++top] = u;
124     instk[u] = 1;
125     for(int i = head[u]; ~i; i=edge[i].next) {
126         v = edge[i].v;
127         if(v == p && (!r)) continue;
128         // if(v == p) continue;
129         if(!dfn[v]) {
130             tarjan(v, u, edge[i].r);
131             low[u] = min(low[u], low[v]);
132             if(low[v] > dfn[u]) edge[i].cut = edge[i^1].cut = 1;
133         }
134         else if(instk[v]) low[u] = min(low[u], dfn[v]);
135     }
136     if(dfn[u] == low[u]) {
137         bcnt++;
138         do {
139             v = stk[top--];
140             instk[v] = 0;
141             belong[v] = bcnt;
142         } while(v != u);
143     }
144 }
145 
146 void dfs(int u) {
147     Rep(i, G[u].size()) {
148         int v = G[u][i];
149         if(dfn[v] != -1) continue;
150         dfn[v] = max(dfn[v], dfn[u] + 1);
151         dfs(v);
152     }
153 }
154 
155 inline bool scan_d(int &num) {
156     char in;bool IsN=false;
157     in=getchar();
158     if(in==EOF) return false;
159     while(in!=-&&(in<0||in>9)) in=getchar();
160     if(in==-){ IsN=true;num=0;}
161     else num=in-0;
162     while(in=getchar(),in>=0&&in<=9){
163             num*=10,num+=in-0;
164     }
165     if(IsN) num=-num;
166     return true;
167 }
168 
169 int main() {
170     // FRead();
171     int u, v;
172     while(~scan_d(n) && ~scan_d(m) && n + m) {
173         init();
174         Rep(i, n+10) G[i].cl();
175         Rep(i, m) {
176             scan_d(u); scan_d(v);
177             if(u == v) continue;
178             if(u > v) swap(u, v);
179             tmp[i] = Tmp(u, v);
180         }
181         sort(tmp, tmp+m, cmp);
182         // m = unique(tmp, tmp+m) - tmp;
183         Rep(i, m) {
184             u = tmp[i].u; v = tmp[i].v;
185             if(i == 0 || (tmp[i].u != tmp[i-1].u || tmp[i].v != tmp[i-1].v)) {
186                 if(i < m - 1 && (tmp[i].u == tmp[i+1].u && tmp[i].v == tmp[i+1].v)) {
187                     adde(u, v, 1); adde(v, u, 1);
188                 }
189                 else {
190                     adde(u, v, 0); adde(v, u, 0);
191                 }
192             }
193         }
194         tarjan(1, 0, 0);
195         For(u, 1, n+1) {
196             for(int i = head[u]; ~i; i=edge[i].next) {
197                 if(edge[i].cut) {
198                     v = edge[i].v;
199                     G[belong[u]].pb(belong[v]);
200                 }
201             }
202         }
203         Clr(dfn, -1); dfn[1] = 0;
204         dfs(1);
205         int pos = 1;
206         For(i, 1, bcnt+1) if(dfn[i] > dfn[pos]) pos = i;
207         Clr(dfn, -1); dfn[pos] = 0;
208         dfs(pos);
209         int ret = 0;
210         Rep(i, bcnt+1) {
211             ret = max(ret, dfn[i]);
212         }
213         printf("%d\n", bcnt - ret - 1);
214     }
215     RT 0;
216 }

 

以上是关于[HDOJ4612]Warm up(双连通分量,缩点,树直径)的主要内容,如果未能解决你的问题,请参考以下文章

hdu4612-Warm up(边的双连通分量)

Warm up HDU - 4612( 树的直径 边双连通分量)

HDOJ4612双连通分量缩点+找树的直径

HDU4612 Warm up

HDU 4612 Warm upBCC 树的直径

HDOJ2242解题报告边双连通分量