zoukankan      html  css  js  c++  java
  • [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
    ", bcnt - ret - 1);
    214     }
    215     RT 0;
    216 }
  • 相关阅读:
    HDMI介绍与流程
    HDMI热插拔检测原理
    在AES标准规范中,分组长度、密钥长度的关系
    WORD-每5行添加一个行号
    FreeRTOS 调试方法(printf---打印任务执行情况)
    SELinux深入理解
    一文彻底明白linux中的selinux到底是什么
    云锵投资 2020 年 06 月简报
    ubuntu16.04 安装opencv-2.4.9
    Windows高DPI系列控件(二)
  • 原文地址:https://www.cnblogs.com/kirai/p/5522853.html
Copyright © 2011-2022 走看看