zoukankan      html  css  js  c++  java
  • TOJ 3365 ZOJ 3232 It's not Floyd Algorithm / 强连通分量

    It's not Floyd Algorithm

    时间限制(普通/Java):1000MS/3000MS     运行内存限制:65536KByte
     

    描述

     

    When a directed graph is given, we can solve its transitive closure easily using the well-known Floyd algorithm.

    But if you're given a transitive closure, can you give a corresponding directed graph with minimal edges?

    输入

     

    About 100 test cases, seperated by blank line.

    First line of each case is an integer N (1<=N<=200). The followingN lines represent the given transitive closure in 0-1 matrix form, each line hasN numbers.

    输出

     

    For each case, just output the number of minimal edges of a directed graph which has a given transitive closure.

    样例输入

     

    1
    1
    
    2
    1 0
    0 1
    
    2
    1 1
    1 1
    
    3
    1 1 1
    0 1 1
    0 0 1
    
    

    样例输出

     

    0
    0
    2
    2
    

    提示

    Transitive closure can be presented as a matrix T, where Ti,j is true if and only if there is a path from vertexi toj.

    首先缩点 在建图 对于每个强连通分量如果有n个点那么最少只需n条边就可以联通(n = 1 除外)

    然后对于缩点后的图咋做一次反闭包 去掉多余的边 在统计一下

    	
    #include<stdio.h>
    #include<string.h>
    int n;
    int dfn[210];
    int low[210];
    bool instack[210];
    int stack[210];
    int cnt,num,top;
    int a[210][210];
    int count[210];
    int belong[210];
    int map[210][210];
    void floyd()
    {
    	int i,j,k;
    	for(k = 1;k <= cnt; k++)
    		for(i = 1;i <= cnt; i++)
    			for(j = 1;j <= cnt; j++)
    				if(map[i][k] && map[k][j] && map[i][j])
    					map[i][j] = 0;
    }
    void tarjan(int i)
    {
            int j,k;
            dfn[i] = low[i] = ++num;
            instack[i] = true;
            stack[++top] = i;
            for(j = 1;j <= n; j++)
            {
                k = a[i][j];
                if(!k)
                	continue;
                if(!dfn[j])
                {
                    tarjan(j);
                    if(low[i] > low[j])
                    	low[i] = low[j];
                }
                else if(instack[j] && low[i] > dfn[j])
                    low[i] = dfn[j];
            } 
            if(low[i] == dfn[i])
            {
                cnt++;
                do
                {
                    j = stack[top--];
                    instack[j] = false;
                    belong[j] = cnt; 
                    count[cnt]++;
                }
                while(i != j);
            }
    } 
    int main()
    {
    	int i,j,sum;
    	while(scanf("%d",&n)!=EOF)
    	{
    		for(i = 1;i <= n; i++)
    			for(j = 1; j<= n; j++)
    				scanf("%d",&a[i][j]);
    		num = top = cnt = 0;
    		memset(dfn,0,sizeof(dfn));
    		memset(instack,false,sizeof(instack));
    		memset(count,0,sizeof(count));
    		memset(map,0,sizeof(map));
    		for(i = 1;i <= n; i++)
    			if(!dfn[i])
    				tarjan(i);
    		for(i = 1; i<= n; i++)
    			for(j = 1; j<= n; j++)
    				if(a[i][j])
    					if(belong[i] != belong[j])
    						map[belong[i]][belong[j]] = 1;
    		sum = 0;
    		floyd();
    		for(i = 1;i <= cnt; i++)
    			if(count[i] != 1)
    				sum += count[i];
    		for(i = 1;i <= cnt; i++)
    			for(j = 1; j<= cnt; j++)
    				if(map[i][j])
    					sum++;
    		printf("%d
    ",sum);
    	}
    	return 0;
    }
    
    
    
    
     
    


     

  • 相关阅读:
    美团面试(c++方向)
    浪潮面试-软开
    ofo C++面试
    B树、B+树等
    爱奇艺2017秋招笔试(C++智能设备方向)
    腾讯内推一面C++
    i++ 相比 ++i 哪个更高效?为什么?
    进程间的通讯(IPC)方式
    一台服务器能够支持多少TCP并发连接呢?
    可重入和不可重入
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3423973.html
Copyright © 2011-2022 走看看