Hdu4370 0 or 1 最短路径spfa

来源:互联网 发布:济宁广电网络客服电话 编辑:程序博客网 时间:2024/05/22 06:04

题意:一个n*n的01矩阵,满足以下条件

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).

另给出一个矩阵C,求∑Cij*Xij(1<=i,j<=n)的最小值。


此题非常厉害,就算法来说不是很难,但很考想法。这题的精髓在于如何将条件抽象出来,并建图。

三个条件分别告诉我们 点1的出度为1,点n的入度为1,每个点的入度等于出度,这样就可以构图了。设n各点,将∑Cij*Xij(1<=i,j<=n)看成n各点的邻接矩阵。这时问题分成了两种情况。

第一种是求1到n的最短路径,第二种是求1到1的非自环闭环 + n到n的非自环闭环的和。比较这两种情况,取最小的值为解。

用spfa时设d[s]的值为INF,让d[s]的相邻节点入栈,这样保证了可以取到非自环闭环。


#include <iostream>#include<cstdio>#include<cstring>#include<cmath>#define INF 0x7fffffff#define N 550using namespace std;int d[N],v[N],n,a[N][N],q[N];int spfa(int s,int t){    for(int i=1;i<=n;i++)        d[i]=INF,v[i]=0;    int cnt=0;    for(int i=1;i<=n;i++)        if(i!=s)        {            d[i]=a[s][i];            q[cnt++]=i;            v[i]=1;        }    while(cnt>=0)    {        int c=q[--cnt];        v[c]=0;        for(int i=1;i<=n;i++)            if(d[i]>d[c]+a[c][i])            {                d[i]=d[c]+a[c][i];                if(!v[i])   v[i]=1,q[cnt++]=i;            }    }    return d[t];}int main(){    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                scanf("%d",&a[i][j]);        int ans=min(spfa(1,n),spfa(1,1)+spfa(n,n));        cout<<ans<<endl;    }}

2 0
原创粉丝点击