• hdu3861 强连通+最小路径覆盖


    题意:有 n 个点,m 条边的有向图,需要将这些点分成多个块,要求:如果两点之间有路径能够互相到达,那么这两个点必须分在同一块;在同一块内的任意两点相互之间至少要有一条路径到达,即 u 到达 v 或 v 到达 u;每个点都只能存在于单独一个块内。问最少需要划分多少块。

    首先,对于如果两点之间能够相互到达则必须在同一块,其实也就是在同一个强连通分量中的点必须在同一块中,所以首先就是强连通缩点。然后在同一块内的任意两点之间要有一条路,那么其实就是对于一块内的强连通分量,至少要有一条路径贯穿所有分量。而这一条路径上的所有强连通分量就可以构成同一块。那么其实我们就是需要找出最少的这样的路径将所有点全部覆盖一遍,就是做一遍最小路径覆盖。

    最小路径覆盖数=点数-拆点后的最大匹配数。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stack>
      4 #include<queue>
      5 using namespace std;
      6 
      7 const int maxn=10005;
      8 const int maxm=2e5+5;
      9 
     10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2];
     11 int n,t,scccnt;
     12 int stx[maxn],low[maxn],scc[maxn];
     13 int vis[maxn],match[maxn];
     14 stack<int>S;
     15 
     16 void init(){
     17     memset(head,-1,sizeof(head));
     18     size[0]=size[1]=0;
     19 }
     20 
     21 void add(int a,int b,int c=0){
     22     point[c][size[c]]=b;
     23     nxt[c][size[c]]=head[c][a];
     24     head[c][a]=size[c]++;
     25 }
     26 
     27 void dfs(int s){
     28     stx[s]=low[s]=++t;
     29     S.push(s);
     30     for(int i=head[0][s];~i;i=nxt[0][i]){
     31         int j=point[0][i];
     32         if(!stx[j]){
     33             dfs(j);
     34             low[s]=min(low[s],low[j]);
     35         }
     36         else if(!scc[j]){
     37             low[s]=min(low[s],stx[j]);
     38         }
     39     }
     40     if(low[s]==stx[s]){
     41         scccnt++;
     42         while(1){
     43             int u=S.top();S.pop();
     44             scc[u]=scccnt;
     45             if(s==u)break;
     46         }
     47     }
     48 }
     49 
     50 void setscc(){
     51     memset(stx,0,sizeof(stx));
     52     memset(scc,0,sizeof(scc));
     53     t=scccnt=0;
     54     for(int i=1;i<=n;++i)if(!stx[i])dfs(i);
     55     for(int i=1;i<=n;++i){
     56         for(int j=head[0][i];~j;j=nxt[0][j]){
     57             int k=point[0][j];
     58             if(scc[i]!=scc[k]){    
     59                 add(scc[i],scc[k]+scccnt,1);
     60             }
     61         }
     62     }
     63 }
     64 
     65 int dfs1(int k){
     66     for(int i=head[1][k];~i;i=nxt[1][i]){
     67         if(!vis[point[1][i]]){
     68             int p=point[1][i];
     69             vis[p]=1;
     70             if(match[p]==-1||dfs1(match[p])){
     71                 match[p]=k;
     72                 return 1;
     73             }
     74         }
     75     }
     76     return 0;
     77 }
     78 
     79 
     80 int main(){
     81     int T;
     82     scanf("%d",&T);
     83     while(T--){
     84         int m;
     85         scanf("%d%d",&n,&m);
     86         init();
     87         while(m--){
     88             int a,b;
     89             scanf("%d%d",&a,&b);
     90             add(a,b);
     91         }
     92         setscc();
     93         int ans=0;
     94         memset(match,-1,sizeof(match));
     95         for(int i=1;i<=2*scccnt;++i){
     96             memset(vis,0,sizeof(vis));
     97             if(dfs1(i)==1)ans++;
     98         }
     99         printf("%d
    ",scccnt-ans);
    100     }
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    css盒模型
    css构造块级元素
    后台数据能刷新,前台页面显示不刷新问题
    java的代理和动态代理简单测试
    基于Maven的S2SH(Struts2+Spring+Hibernate)框架搭建
    SSH框架中配置log4j的方法
    Spring声明式事务配置管理方法
    Hibernate关联关系配置(一对多、一对一和多对多)
    java递归和反向递归
    Java实现几种常见排序方法
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4811732.html
Copyright © 2020-2023  润新知