hdu 4370 思维最短路 看到矩阵要想到图

题意:

n*n的非负整数矩阵C,请自制一个元素为0或1的n*n矩阵X。输出∑C ij*X ij(1<=i,j<=n)。矩阵X满足如下三个条件。

1.X 12+X 13+...X 1n=1。
2.X 1n+X 2n+...X n-1n=1。
3.对每一个1<i<n范围内的i,满足 ∑X ki (1<=k<=n)=∑X ij (1<=j<=n)。

题解:

1.这道题看似无从下手,但一定要记住,矩阵可以看作邻接矩阵存储的图!!!

2.条件1:第1个结点的出度为1(由1指向1的单边不计入此出度)。

   条件2:第n个结点的入度为1(由n指向n的单边不计入此入度)。

   条件3:第i个结点(1<i<n)的入度和出度相等。

3.根据这三个条件可分类讨论:

   若第i个结点(1<i<n)的入度和出度为0,那么第1个结点和第2个结点需要一个经过其他结点的环,计算这两个环的权值和。

   若第i个结点(1<i<n)的入度和出度为1,那么第1个结点和第2个结点不需要环,计算从1到n的最短路径。

扫描二维码关注公众号,回复: 5093055 查看本文章

4.输出这两个环的权值和、从1到n的最短路径的最小值即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
int n ;
bool vis[305] ;
int map1[305][305] ;
int dis[305] ;
int spfa(int start)
{
	int i , j , k ;
	int a , b ;
	queue <int> q ;
	memset(dis , inf , sizeof(dis)) ;
	for(i = 1 ; i <= n ; i ++)
	{   
	    dis[i] = map1[start][i] ; 
		q.push(i) ;
	}
	dis[start] = inf ;
	while(!q.empty())
	{
	   a = q.front() ;
	   q.pop() ;
	   for(i = 1 ; i <= n ; i ++)
	   {
	   	   if(a == i)
			  continue ; 
		   if(dis[a] + map1[a][i] < dis[i])
	       {
	       	 dis[i] = dis[a] + map1[a][i] ;
	       	 q.push(i) ;
		   }  	         
	   }
	} 
}
int main()
{
  int i , j , k ;
  int sp , s1 , s2 , ans ;
  while(scanf("%d" , &n) != EOF)
  {
    for(i = 1 ; i <= n ; i ++)
        for(j = 1 ; j <= n ; j ++)
            scanf("%d" , &map1[i][j]) ;
    spfa(1) ;
	sp = dis[n] ;
	s1 = dis[1] ;
	spfa(n) ;
	s2 = dis[n] ;
	ans = min(sp , s1 + s2) ;
	printf("%d\n" , ans) ;	
  }
}

猜你喜欢

转载自blog.csdn.net/Irving0323/article/details/86662727
今日推荐