题意:
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的最短路径。
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) ;
}
}