随笔 - 97, 文章 - 22, 评论 - 81, 引用 - 0
数据加载中……

HDOJ 1625 Numbering Paths (DP)

问题描述:
给定一张有向图邻接表,求任意点对间的路径数。

解题思路:
首先floyed一遍,确定任意点对间是否可达,然后枚举点对进行记忆化搜索。具体思路就是如果i到k有边,k能够到达j,那么k到达j的路径数必定是i到j路径数的子集。枚举所有和i邻接的k即可。但是这道题目有可能有环,题目要求有环认为无穷路径,这样处理起来也是很方便的,可以这样想,如果i到k有边,但是k到j没有路径,那么即使k点存在一个环也对i到j的路径数没有任何影响,但是如果k有环,而且k可以到达j,那么i到j就必定有无穷多条路径了(因为可以在到达k的时候绕着环走啊走......),之后求出所有点对间的路径即可。

代码如下:
#include <iostream>
#include 
<vector>
using namespace std;

int map[101][101];
vector 
< int > vec[101];
int n;
int dp[101][101];

int dfs(int start, int end) {

    
int i, size = vec[start].size();
    
int sum = 0;

    
if(!map[start][end] && start != end)
        
return 0;

    
if(map[start][end] && map[end][start])
        
return -2;

    
if(start == end)
        
return 1;

    
for(i = 0; i < size; i++{
        
int u = vec[start][i];
        
        
if(map[u][start] && map[start][u])
            
return -2;

        
if(dp[u][end] == -1)
            dp[u][end] 
= dfs(u, end);

        
if(dp[u][end] == -2)
            
return -2;

        sum 
+= dp[u][end];
    }

    
return sum;
}


int main()
    
int m, i, j, k, x, y;
    
int cas = 0;

    
while(scanf("%d"&m) != EOF) {
        memset(map, 
0sizeof(map));
        
for(i = 0; i < 101; i++)
            vec[i].clear();
        n 
= 0;
        
while(m--{
            scanf(
"%d %d"&x, &y);
            map[x][y] 
= 1;
            vec[x].push_back( y );
            
if(x > n) n = x;
            
if(y > n) n = y;
        }


        
for(k = 0; k <= n; k++{
            
for(i = 0; i <= n; i++{
                
for(j = 0; j <= n; j++{

                    
if(map[i][k] && map[k][j])
                        map[i][j] 
= 1;
                }

            }

        }


        memset(dp, 
-1sizeof(dp));
        
for(i = 0; i <= n; i++{
            
for(j = 0; j <= n; j++{

                
if(dp[i][j] == -1)
                    dp[i][j] 
= dfs(i, j);
            }

        }

        
        printf(
"matrix for city %d\n", cas++);

        
for(i = 0; i <= n; i++{
            
for(j = 0; j <= n; j++{

                
if(i == j) {
                    
if(dp[i][j] == -2)
                        printf(
" -1");
                    
else
                        printf(
" 0");
                }
else {
                    
if(dp[i][j] == -2)
                        printf(
" -1");
                    
else
                        printf(
" %d", dp[i][j]);
                }

            }

            puts(
"");
        }


    }

    
return 0;
}



posted on 2009-03-02 18:39 英雄哪里出来 阅读(287) 评论(0)  编辑 收藏 引用 所属分类: ACM


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理