zoukankan      html  css  js  c++  java
  • 【HDU3861 强连通分量缩点+二分图最小路径覆盖】

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

    题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少。

    规则如下:1、有边u到v以及有边v到u,则u,v必须划分到同一个区域内。2、一个区域内的两点至少要有一方能到达另一方。3、一个点只能划分到一个区域内。

    解题思路:根据规则1可知必然要对强连通分量进行缩点,缩点后变成了一个弱连通图。根据规则2、3可知即是要求图的最小路径覆盖。

    定义:

    最小路径覆盖:在图中找一些路径(路径数最少),使之覆盖了图中所有的顶点,且每个顶点有且仅和一条路径有关联。

    最小顶点覆盖:在图中找一些点(顶点数最少),使之覆盖了图中所有的边,每条边至少和一个顶点有关联。

    二分图:最小顶点覆盖=最大匹配数。

                最小路径覆盖=顶点数-最大匹配数。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <algorithm>
      5 #include <cstring>
      6 using namespace std;
      7 
      8 const int maxn=55555;
      9 int  dfn[maxn], low[maxn], stack[maxn], belong[maxn], visit[maxn], match[maxn];
     10 bool instack[maxn];
     11 int top, scnt, Index, n, m, T;
     12 vector<int>vt[maxn];
     13 
     14 struct Node
     15 {
     16     int u, v;
     17 }f[2*maxn];
     18 
     19 void Init_tarjan()
     20 {
     21     top=scnt=Index=0;
     22     for(int i=1; i<=n; i++) dfn[i]=low[i]=instack[i]=0;
     23 }
     24 
     25 void tarjan(int u)
     26 {
     27     stack[++top]=u;
     28     dfn[u]=low[u]=++Index;
     29     instack[u]=1;
     30     for(int i=0; i<vt[u].size(); i++)
     31     {
     32         int v=vt[u][i];
     33         if(!dfn[v])
     34         {
     35             tarjan(v);
     36             low[u]=min(low[u],low[v]);
     37         }
     38         else if(instack[v])
     39         {
     40             low[u]=min(low[u],dfn[v]);
     41         }
     42     }
     43     if(low[u]==dfn[u])
     44     {
     45         int v;
     46         scnt++;
     47         do
     48         {
     49             v=stack[top--];
     50             instack[v]=0;
     51             belong[v]=scnt;
     52         }
     53         while(u!=v);
     54     }
     55 }
     56 
     57 bool find(int u)
     58 {
     59     for(int i=0; i<vt[u].size(); i++)
     60     {
     61         int v=vt[u][i];
     62         if(!visit[v])
     63         {
     64             visit[v]=1;
     65             if(match[v]==-1||find(match[v]))
     66             {
     67                 match[v]=u;
     68                 return true;
     69             }
     70         }
     71     }
     72     return false;
     73 }
     74 
     75 int hungary()
     76 {
     77     int cnt=0;
     78     memset(match,-1,sizeof(match));
     79     for(int i=1; i<=scnt; i++)
     80     {
     81         for(int j=1; j<=scnt; j++) visit[j]=0;
     82         if(find(i)) cnt++;
     83     }
     84     return cnt;
     85 }
     86 
     87 int main()
     88 {
     89     cin >> T;
     90     while(T--)
     91     {
     92         cin >> n >> m;
     93         for(int i=0; i<=n; i++) vt[i].clear();
     94         for(int i=0; i<m; i++)
     95         {
     96             scanf("%d%d",&f[i].u,&f[i].v);
     97             vt[f[i].u].push_back(f[i].v);
     98         }
     99         Init_tarjan();
    100         for(int i=1; i<=n; i++)
    101             if(!dfn[i]) tarjan(i);
    102         for(int i=0; i<=n; i++) vt[i].clear();
    103         for(int i=0; i<m; i++)
    104         {
    105             int u=belong[f[i].u], v=belong[f[i].v];
    106             if(u==v) continue;
    107             vt[u].push_back(v);
    108         }
    109         int ans=hungary();
    110         cout << scnt-ans <<endl;
    111     }
    112     return 0;
    113 }
    114 
    115 /*
    116 10
    117 10 11
    118 1 2
    119 2 3
    120 3 1
    121 3 4
    122 5 6
    123 6 7
    124 7 5
    125 4 5
    126 10 9
    127 9 8
    128 8 4
    129 2
    130 */
    View Code
  • 相关阅读:
    操作元素
    CSS3 制作网格动画效果
    网页边栏过渡动画
    超炫的 CSS3 页面切换动画效果
    多种鼠标悬停效果
    各种 SVG 制作单选和多选框动画
    全屏遮罩层效果(10种)
    FancyBox – 经典 Lightbox 效果插件
    CSS3 & SVG 制作钟表
    20种新颖的按钮风格和效果【附源码】
  • 原文地址:https://www.cnblogs.com/kane0526/p/3203992.html
Copyright © 2011-2022 走看看