zoukankan      html  css  js  c++  java
  • UVALive 4287 Proving Equivalences(缩点)

    等价性问题,给出的样例为 a->b的形式,问要实现全部等价(即任意两个可以互相推出),至少要加多少个形如 a->b的条件。

    容易想到用强连通缩点,把已经实现等价的子图缩掉,最后剩余DAG。要推出一个方案,YY后取“出度为零”和“入度为零”的点数的较大值。

    理由:假定出度为零的点数较多,即是我们通常意义上的树的形式(当然,DAG是图,这里只是类比)。

    根可以推出其所有子孙,事实上任意一个点都可以推出其子孙,那么只要让该节点推出树根,就可以推出整棵树上所有的节点了。那么多棵树为什么不是相乘呢?,借题目中的范例,a->b,b->c,c->a,形成一个循环即可。

    本质:给定一个有向图,问是否加上多少条边,使原图构成强连通。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stack>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 const int MAXN=55555;
      8 
      9 struct Edge{
     10     int v,next;
     11     Edge(){}
     12     Edge(int _v,int _next):v(_v),next(_next){}
     13 }edge[MAXN];
     14 
     15 int tol,head[MAXN];
     16 int low[MAXN],dfn[MAXN],sccno[MAXN],scc_cnt,TT;
     17 
     18 stack<int >stk;
     19 
     20 void init()
     21 {
     22     tol=0;
     23     memset(head,-1,sizeof(head));
     24 }
     25 
     26 void add(int u,int v)
     27 {
     28     edge[tol]=Edge(v,head[u]);
     29     head[u]=tol++;
     30 }
     31 
     32 void dfs(int u)
     33 {
     34     int v;
     35     dfn[u]=low[u]=++TT;
     36     stk.push(u);
     37     for(int i=head[u];i!=-1;i=edge[i].next)
     38     {
     39         v=edge[i].v;
     40         if(!dfn[v]){
     41             dfs(v);
     42             low[u]=min(low[u],low[v]);
     43         }else if(!sccno[v]){
     44             low[u]=min(low[u],dfn[v]);
     45         }
     46     }
     47     if(low[u]==dfn[u]){
     48         scc_cnt++;
     49         do{
     50             v=stk.top();
     51             stk.pop();
     52             sccno[v]=scc_cnt;
     53         }while(v!=u);
     54     }
     55 }
     56 
     57 void tarjan(int n)
     58 {
     59     scc_cnt=TT=0;
     60     memset(low,0,sizeof(low));
     61     memset(dfn,0,sizeof(dfn));
     62     memset(sccno,0,sizeof(sccno));
     63 
     64     while(!stk.empty())
     65         stk.pop();
     66     for(int i=1;i<=n;i++)
     67         if(!dfn[i])
     68             dfs(i);
     69 }
     70 
     71 int main()
     72 {
     73     int T,n,m;
     74     int a[MAXN],b[MAXN];
     75     scanf("%d",&T);
     76     while(T--)
     77     {
     78         scanf("%d%d",&n,&m);
     79 
     80         init();
     81         for(int i=0;i<m;i++)
     82         {
     83             scanf("%d%d",&a[i],&b[i]);
     84             add(a[i],b[i]);
     85         }
     86 
     87         tarjan(n);
     88 
     89         int in[MAXN],out[MAXN];
     90         memset(in,0,sizeof(in));
     91         memset(out,0,sizeof(out));
     92         for(int i=0;i<m;i++)
     93         {
     94             if(sccno[a[i]]!=sccno[b[i]]){
     95                 in[sccno[b[i]]]++;
     96                 out[sccno[a[i]]]++;
     97             }
     98         }
     99 
    100         int innum,outnum;
    101         innum=outnum=0;
    102         for(int i=1;i<=scc_cnt;i++)
    103         {
    104             if(!in[i])
    105                 innum++;
    106             if(!out[i])
    107                 outnum++;
    108         }
    109 
    110         if(scc_cnt==1)printf("0
    ");
    111         else printf("%d
    ",max(innum,outnum));
    112     }
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    [置顶] 基于平板电脑的面访调查
    spring技术翻译开始
    (3)选择元素——(9)为交替的列加样式(Styling alternate rows)
    网页换肤
    djano-cms学习笔计(一)
    【Android】Activity的菜单机制和方法解析
    canvas
    Flexbox-CSS3弹性盒模型flexbox完整版教程
    原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y
    怎么使用jquery判断一个元素是否含有一个指定的类(class)
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3239781.html
Copyright © 2011-2022 走看看