HDU 4370 0 or 1 【spfa求正环花费+矩阵思维转换】

HDU 4370 0 or 1

题目链接:vjudge传送门

题目大意:
其实理解了题目的深层意思,思路基本上就有了,就是把邻居矩阵和图相结合。
给定一个n维矩阵A,求一个n维矩阵B(矩阵元素为1或0),使得两个矩阵对应位置上的元素相乘的和最小。求和(Aij xBij),结果最小。
其中B矩阵需要满足以下三条:

  1. X12+X13+…X1n=1 //代表1号点出度为0
  2. X1n+X2n+…Xn-1n=1 //代表n号点入度为0
  3. for each i (1

具体思路
求AB矩阵对应位置相乘和最小,又B矩阵元素为0或1,可知在满足以上三条的情况下,当为0的元素越多,最终求得的和就会越少。
又B矩阵上某个位置为0,可以看成i->j的边不存在
因此问题可以转换成求1号点到n号点的最短距离,刚好满足1号入度为0,n号出度为0,其余点出度入度相等(要么0,要么1)

但是除了这种最短路的情况满足三个条件,还有一种情况也满足:

  • 从1号点出发经过除n号点的任意点然后回到1号点的环路
  • 从n号点出发经过除1号点的任意点然后回到n号点的环路
    两个环路构成的图刚好也满足三个条件,因此结果需在最短距离最小二环距离之和中取较小值

思路来源:https://xiaoxiaoh.blog.csdn.net/article/details/104216564

具体代码:
spfa求最短路以及正环花费

求不带负权的环花费的算法,可以改进spfa算法,初始化d[start] = INF,d[other]=weight(s->other),并将处s外的点入队

#include
#include
#include
#include
#include
using namespace std;
int const N = 310;
int const INF = 0x3f3f3f3f;
int maps[N][N];
int d[N],visit[N];
int n;

void dijkstra(int s)
{
     
	memset(visit, 0, sizeof(visit));
	memset(d, 0x3f, sizeof(d));
	queue<int> q;
	for (int i = 1; i <= n; i++)
	{
     
		if (i == s)d[i] = INF;
		else {
     
			d[i] = maps[s][i];
			q.push(i);
			visit[i] = 1;
		}
	}
	while (q.size())
	{
     
		int t = q.front();
		q.pop();
		visit[t] = 0;
		for (int i = 1;i<=n; i++)
		{
     
			if(d[i]>d[t]+maps[t][i])
			{
     
				d[i] = d[t] + maps[t][i];
				q.push(i);
			}
		}
	}
}
int main()
{
     
	while (~scanf("%d", &n))
	{
     
		for (int i = 1; i <= n; i++)
		{
     
			for (int j = 1; j <= n; j++)
			{
     
				scanf("%d", &maps[i][j]);
			}
		}
		int path, cir_1, cir_n;
		dijkstra(1);
		path = d[n];
		cir_1 = d[1];
		dijkstra(n);
		cir_n = d[n];
		printf("%d\n", path < cir_1 + cir_n ? path : cir_1 + cir_n);
	}
	return 0;
}

你可能感兴趣的:(最短路,OJ题解)