0 or 1 HDU - 4370 (spfa) 最短路专题
题目描述
Given a n*n matrix Cij (1<=i,j<=n),We want to find a n*n matrix Xij (1<=i,j<=n),which is 0 or 1.
Besides,Xij meets the following conditions:
1.X12+X13+...X1n=1
2.X1n+X2n+...Xn-1n=1
3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).
For example, if n=4,we can get the following equality:
X12+X13+X14=1
X14+X24+X34=1
X12+X22+X32+X42=X21+X22+X23+X24
X13+X23+X33+X43=X31+X32+X33+X34
Now ,we want to know the minimum of ∑Cij*Xij(1<=i,j<=n) you can get.Input
The input consists of multiple test cases (less than 35 case).
For each test case ,the first line contains one integer n (1<n<=300).
The next n lines, for each lines, each of which contains n integers, illustrating the matrix C, The j-th integer on i-th line is Cij(0<=Cij<=100000).Output
For each case, output the minimum of ∑Cij*Xij you can get.
题目大意:给你一个n*n 的矩阵,让你找出一个满足上述条件的矩阵,使得这两个矩阵每个相同位置相乘的总和最小。
解题思路: 由于在最短路专题做到,可以看出这道题就是把题意转化为最短路的思想。
把要让我们写出的矩阵看成n个点的邻接矩阵。
观察让我们写出的矩阵:1、X12+X13+...X1n=1 可以看成是点1的出度为1
2、X1n+X2n+...Xn-1n=1 可以看成点n的入度为1
3、for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n) 可以看成其它点入度和出度相等
输入的矩阵即是这n个点相互之间的花费,因此让我们求的就是,1~n的最小花费或者是1的环加上n的环的最小花费。
答案就是这两者的最小值。
spfa的有一种操作是可以求单源最小环的,即初始化dis[start] = INF,且一开始让源点之外的点入队
代码:
#include<bits/stdc++.h>
#define ll long long
#define MOD 998244353
#define INF 0x3f3f3f3f
#define mem(a,x) memset(a,x,sizeof(a))
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
int mp[305][305];
int n;
int dis[305];
bool vis[305];
void spfa(int start)
{
queue<int>Q;
for(int i=1;i<=n;i++){
dis[i]=mp[start][i];
if(i!=start){
Q.push(i);
vis[i]=true;
}else{
vis[i]=false;
}
}
dis[start]=INF;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
vis[u]=false;
for(int i=1;i<=n;i++){
if(i==u)continue;
if(dis[i]>dis[u]+mp[u][i]){
dis[i]=dis[u]+mp[u][i];
if(!vis[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",&mp[i][j]);
}
}
spfa(1);
int num1=dis[n];
int num2=dis[1];
spfa(n);
int num3=dis[n];
cout<<min(num1,num2+num3)<<endl;
}
return 0;
}