HDU 4370 - 0 or 1 (SPFA+思维)
题意:给一个N*N的矩阵C,和一个N*N的只由0和1组成的矩阵X。
X满足以下条件:
1.X 12+X 13+...X 1n=1
2.X 1n+X 2n+...X n-1n=1
3.任意 i (1<i<n), 都有 ∑X ki (1<=k<=n)=∑X ij (1<=j<=n).
求∑C ij*X ij(1<=i,j<=n) 的最小值(1<n<=300)。
分析:乍一看也想不到这是道最短路的题。但将模型转换后,则易想到方法。根据01矩阵X满足的条件,可将其转化为一张图,其满足条件为:点1的出度为1;点N的入度为1;任意点v(1<v<n)的入度等于出度。再用矩阵C视作边权,Cij即边 (i,j)的权值,建图。
所求的答案是min(1->N最短路的值,或由点1出发的环加上由点N出发的环的值)。用SPFA分别对点1、点N跑两次最短路。结果即min(d[N],cir[1]+cir[N])。
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 305;
struct Spfa{
int N;
int G[maxn][maxn];
int d[maxn];
bool vis[maxn];
void init(int N){ this->N=N;}
void spfa(int s){
memset(vis,0,sizeof(vis));
queue<int> Q;
for(int i=1;i<=N;++i){
d[i]=G[s][i];
if(i!=s){
Q.push(i);
vis[i]= true;
}
}
d[s]=INF;
while(!Q.empty()){
int x =Q.front();Q.pop();
vis[x] = false;
for(int i =1;i<=N;++i){
if(x==i) continue;
if(d[i]>d[x]+G[x][i]){
d[i]=d[x]+G[x][i];
if(!vis[i]){
Q.push(i);
vis[i]=true;
}
}
}
}
}
}G;
#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int N,M,s,t,u,v,T,tmp;
while(~scanf("%d",&N)){
if(!N) break;
G.init(N);
for(int i =1;i<=N;++i){
for(int j=1;j<=N;++j){
scanf("%d",&G.G[i][j]);
}
}
G.spfa(1);
int res=G.d[N];
int cir1=G.d[1];
G.spfa(N);
int cir2 = G.d[N];
res=min(res,cir1+cir2);
printf("%d\n",res);
}
return 0;
}
为了更好的明天

浙公网安备 33010602011771号