• loj 1429(可相交的最小路径覆盖)


    题目链接:http://lightoj.com/volume_showproblem.php?problem=1429

    思路:这道题还是比较麻烦的,对于求有向图的可相交的最小路径覆盖,首先要解决成环问题,可以先染色缩点重建图,然后就是如何来处理这个路径可以相交这个问题,这里可以用bfs求出任意两点之间是否可达,如果可达,就连边,然后就是HK算法求最大匹配了,最小路径覆盖 = 顶点数 - 最大匹配。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 #include <stack>
      8 using namespace std;
      9 
     10 const int MAXN = (1000 + 10);
     11 const int MAXM = (10000 + 10);
     12 int n, m;
     13 int cnt, scc_count;
     14 bool Instack[MAXN];
     15 int low[MAXN], dfn[MAXN], color[MAXN];
     16 vector<int > g[MAXN];
     17 stack<int > S;
     18 
     19 void Tarjan(int u)
     20 {
     21     low[u] = dfn[u] = ++cnt;
     22     Instack[u] = true;
     23     S.push(u);
     24     for (int i = 0; i < (int)g[u].size(); i++) {
     25         int v = g[u][i];
     26         if (dfn[v] == 0) {
     27             Tarjan(v);
     28             low[u] = min(low[u], low[v]);
     29         } else if (Instack[v]) {
     30             low[u] = min(low[u], dfn[v]);
     31         }
     32     }
     33     if (low[u] == dfn[u]) {
     34         scc_count++;
     35         int v;
     36         do {
     37             v = S.top();
     38             S.pop();
     39             Instack[v] = false;
     40             color[v] = scc_count;
     41         } while (u != v);
     42     }
     43 }
     44 
     45 bool Isok[MAXN][MAXN];
     46 bool mark[MAXN];
     47 vector<int > reg[MAXN];
     48 
     49 void bfs(int st)
     50 {
     51     memset(mark, false, sizeof(mark));
     52     queue<int >que;
     53     que.push(st);
     54     mark[st] = true;
     55     while (!que.empty()) {
     56         int u = que.front();
     57         que.pop();
     58         for (int i = 0; i < (int)reg[u].size(); i++) {
     59             int v = reg[u][i];
     60             if (!mark[v]) {
     61                 mark[v] = true;
     62                 que.push(v);
     63             }
     64         }
     65     }
     66 }
     67 
     68 void Build()
     69 {
     70     for (int i = 1; i <= scc_count; i++) {
     71         reg[i].clear();
     72     }
     73     for (int i = 1; i <= scc_count; i++) {
     74         for (int j = 1; j <= scc_count; j++) {
     75             if (i != j && Isok[i][j]) {
     76                 reg[i].push_back(j);
     77             }
     78         }
     79     }
     80 }
     81 
     82 int lx[MAXN], ly[MAXN];
     83 int distx[MAXN], disty[MAXN];
     84 
     85 bool MaxMatch_bfs()
     86 {
     87     bool flag = false;
     88     memset(distx, 0, sizeof(distx));
     89     memset(disty, 0, sizeof(disty));
     90     queue<int > que;
     91     for (int i = 1; i <= scc_count; i++) {
     92         if (lx[i] == -1) que.push(i);
     93     }
     94     while (!que.empty()) {
     95         int u = que.front();
     96         que.pop();
     97         for (int i = 0; i < (int)reg[u].size(); i++) {
     98             int v = reg[u][i];
     99             if (disty[v] == 0) {
    100                 disty[v] = distx[u] + 1;
    101                 if (ly[v] == -1) flag = true;
    102                 else {
    103                     distx[ly[v]] = disty[v] + 1;
    104                     que.push(ly[v]);
    105                 }
    106             }
    107         }
    108     }
    109     return flag;
    110 }
    111 
    112 int dfs(int u)
    113 {
    114     for (int i = 0; i < (int)reg[u].size(); i++) {
    115         int v = reg[u][i];
    116         if (disty[v] == distx[u] + 1) {
    117             disty[v] = 0;
    118             if (ly[v] == -1 || dfs(ly[v])) {
    119                 ly[v] = u;
    120                 lx[u] = v;
    121                 return 1;
    122             }
    123         }
    124     }
    125     return 0;
    126 }
    127 
    128 int MaxMatch()
    129 {
    130     memset(lx, -1, sizeof(lx));
    131     memset(ly, -1, sizeof(ly));
    132     int res = 0;
    133     while (MaxMatch_bfs()) {
    134         for (int i = 1; i <= scc_count; i++) {
    135             if (lx[i] == -1) res += dfs(i);
    136         }
    137     }
    138     return res;
    139 }
    140 
    141 
    142 int main()
    143 {
    144     int _case, t = 1;
    145     scanf("%d", &_case);
    146     while (_case--) {
    147         scanf("%d %d", &n, &m);
    148         for (int i = 1; i <= n; i++) {
    149             g[i].clear();
    150             reg[i].clear();
    151         }
    152         while (m--) {
    153             int u, v;
    154             scanf("%d %d", &u, &v);
    155             g[u].push_back(v);
    156         }
    157         //强联通缩点重建图
    158         cnt = scc_count = 0;
    159         memset(dfn, 0, sizeof(dfn));
    160         for (int i = 1; i <= n; i++) {
    161             if (dfn[i] == 0) Tarjan(i);
    162         }
    163         for (int u = 1; u <= n; u++) {
    164             for (int i = 0; i < (int)g[u].size(); i++) {
    165                 int v = g[u][i];
    166                 if (color[u] != color[v]) {
    167                     reg[color[u]].push_back(color[v]);
    168                 }
    169             }
    170         }
    171         //bfs求出新图中的任意两点之间是否可达
    172         memset(Isok, false, sizeof(Isok));
    173         for (int i = 1; i <= scc_count; i++) {
    174             bfs(i);
    175             for (int j = 1; j <= scc_count; j++) {
    176                 if (mark[j]) {
    177                     Isok[i][j] = true;
    178                 }
    179             }
    180         }
    181         //对于那些可达的点重新连边
    182         Build();
    183         //bfs求解最大匹配;
    184         //最小路径覆盖 = 顶点数 - 最大匹配数
    185         int ans = MaxMatch();
    186         printf("Case %d: %d
    ", t++, scc_count- ans);
    187     }
    188     return 0;
    189 }
    View Code
  • 相关阅读:
    C# 函数式编程
    【python】 入门 搭建环境
    luogu P3978 [TJOI2015]概率论
    luogu P4778 Counting swaps
    luogu P2480 [SDOI2010]古代猪文
    luogu P3243 [HNOI2015]菜肴制作
    luogu P4744 [Wind Festival]Iron Man
    luogu P4448 [AHOI2018初中组]球球的排列
    luogu P1593 因子和
    luogu P1943 LocalMaxima_NOI导刊2009提高(1)
  • 原文地址:https://www.cnblogs.com/wally/p/3532663.html
Copyright © 2020-2023  润新知