zoukankan      html  css  js  c++  java
  • zoj 3232 It's not Floyd Algorithm(强联通分量,缩点)

    题目

    /******************************************************************/

    以下题解来自互联网:Juny的博客

    思路核心:给你的闭包其实就是一个有向图;
    方法:

    1,对此图进行缩点,对于点数为n(n>1)的强连通分量最少要 n 条边,

    对点数为 1 的强连通不需要边,这样计算出边数 m1 ;
    2,在缩点后的有向无环图中进行反floyd,如果有边a->b,b->c,a->c那么显然a->c可以去掉,

    就这样一直去除这样的边,直到不能再去为止,算出最终边数 m2;
    3,m1+m2 即为答案;

    这样做速度比较慢,但小草还没想出其他好的办法,希望有大牛指点……

    /*****************************************************************/

    #include <iostream>  
    #include <cstring>  
    #include <cstdio>  
    #include <cstdlib>  
    using namespace std; 
     
    #define MAXN 20010  
    #define MAXM 50010  
     
    struct Edge 
    { 
          int v, next;   
    }edge[MAXM];    //边结点数组   
     
    int first[MAXN], stack[MAXN], DFN[MAXN], Low[MAXN], Belong[MAXM]; 
    // first[]头结点数组,stack[]为栈,DFN[]为深搜次序数组,
    //Belong[]为每个结点所对应的强连通分量标号数组   
    // Low[u]为u结点或者u的子树结点所能追溯到的最早栈中结点的次序号   
    int instack[MAXM],num[MAXN];  // instack[]为是否在栈中的标记数组   
    int n, m, cnt, scnt, top, tot; 
     
    void init() 
    { 
        cnt = 0; 
        scnt = top = tot = 0;
        memset(first, -1, sizeof(first)); 
        memset(DFN, 0, sizeof(DFN));  
        memset(num,0,sizeof(num));   
    }
     
    void read_graph(int u, int v)   
    { 
         edge[tot].v = v; 
         edge[tot].next = first[u]; 
         first[u] = tot++; 
    } 
     
    void Tarjan(int v)        
    { 
         int  t; 
         DFN[v] = Low[v] = ++cnt;     
         instack[v] = 1;       
         stack[top++] = v;         
         for(int e = first[v]; e != -1; e = edge[e].next) 
         {      
               int j = edge[e].v;   
               if(!DFN[j]) 
               {    
                   Tarjan(j);    
                   if(Low[v] > Low[j]) Low[v] = Low[j]; 
                     
               }
               else if(instack[j] && DFN[j] < Low[v]) 
               {      
                   Low[v] = DFN[j]; 
               }
         } 
         if(DFN[v] == Low[v]) 
         {     
               scnt++;    
               do 
               { 
                   t = stack[--top];     
                   instack[t] = 0;   
                   Belong[t] = scnt;  //为缩点做准备的
                   num[scnt]++;
               }while(t != v); 
         } 
    } 
     
    void solve() 
    { 
         for(int i = 1; i <= n; i++) 
            if(!DFN[i])   
               Tarjan(i); 
    } 
     
    
    int main()
    {
        int i,j,map[210][210],sum1,ans,map1[210][210];//map1[][]是缩点后新建的图
        while(scanf("%d",&n)!=EOF)
        {
            init();
            ans=0;
            memset(map,0,sizeof(map));
            memset(map1,0,sizeof(map1));
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    scanf("%d",&map[i][j]);
                    if(map[i][j]==1&&i!=j)
                    {
                        read_graph(i,j);
                    }
                }
            }
            solve();
            sum1=0;
            for(i=1;i<=scnt;i++)
            {
                if(num[i]>1)
                    sum1+=num[i];
            }
            for(int ii=1;ii<=n;ii++)
            {
                for(int jj=1;jj<=n;jj++)
                {
                    if(map[ii][jj]&&Belong[ii]!=Belong[jj])
                        map1[Belong[ii]][Belong[jj]]=1;
                }
            }
            for(int ii=1;ii<=scnt;ii++)
                for(int jj=1;jj<=scnt;jj++)
                    for(int kk=1;kk<=scnt;kk++)
                        if(map1[ii][jj]&&map1[ii][kk]&&map1[kk][jj])//此处在缩点新建图
                            map1[ii][jj]=0;
            for(int ii=1;ii<=scnt;ii++)
                for(int jj=1;jj<=scnt;jj++)
                    if(map1[ii][jj])
                            ans++;
            printf("%d
    ",sum1+ans);
        }
        return 0;
    }
    View Code
    一道又一道,好高兴!
  • 相关阅读:
    MeteoInfoLab脚本示例:Trajectory
    MeteoInfoLab脚本示例:闪电位置图
    MeteoInfoLab脚本示例:AVHRR HDF数据
    发布MeteoInfo 1.2.8
    切图,css注意事项
    C# Winform下一个热插拔的MIS/MRP/ERP框架15(窗体基类场景1)
    Xamarin Android Webview中JS调用App中的C#方法
    C# Winform下一个热插拔的MIS/MRP/ERP框架14(自动更新)
    C# Winform下一个热插拔的MIS/MRP/ERP框架13(窗体基类)
    RDLC报表的相关技巧四(报表内依照分组重置页码)
  • 原文地址:https://www.cnblogs.com/laiba2004/p/3532936.html
Copyright © 2011-2022 走看看