0 or 1 HDU - 4370(最短路)

 Given a n*n matrix C ij (1<=i,j<=n),We want to find a n*n matrix X ij (1<=i,j<=n),which is 0 or 1.

Besides,X ij meets the following conditions:

1.X 12+X 13+...X 1n=1
2.X 1n+X 2n+...X n-1n=1
3.for each i (1<i<n), satisfies ∑X ki (1<=k<=n)=∑X ij (1<=j<=n).

For example, if n=4,we can get the following equality:

X 12+X 13+X 14=1
X 14+X 24+X 34=1
X 12+X 22+X 32+X 42=X 21+X 22+X 23+X 24
X 13+X 23+X 33+X 43=X 31+X 32+X 33+X 34

Now ,we want to know the minimum of ∑C ij*X ij(1<=i,j<=n) you can get.
Hint

题意:表示1号点出度为1,表示n号点入度为1,表示k( 1 < k < n )号点出度等于入度。∑Cij*Xij(1<=i,j<=n),很明显,这是某个路径的花费,而路径的含义可以有以下两种:
一:1号点到n号点的花费
二:1号点经过其它点成环,n号点经过其它点成环,这两个环的花费之和
于是,就变成了一道简单的最短路问题
关于环花费的算法,可以改进spfa算法,初始化dis[start] = INF,且一开始让源点之外的点入队
4
1 2 4 10
2 0 1 1
2 2 0 5
6 3 1 2

Sample Output

3

Input
The input consists of multiple test cases (less than 35 case).
For each test case ,the first line contains one integer n (1

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stack>
#define INF 0x3f3f3f3f
using namespace std;
int cost[550][550];
int dis[500],vis[500];
int n;
int min(int a,int b)
{
   return  a < b ? a : b;
}
void spfa(int start)
{
    stack<int>Q;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
       dis[i] = cost[start][i];
       if(i!=start)
       {
          Q.push(i);
          vis[i] = 1;
       }
    }
    dis[start] = INF;
    while(!Q.empty())
    {
       int x = Q.top();
       Q.pop();
       vis[x] = 0;
       for(int y = 1;y<=n;y++)
       {
          if(x==y) continue;
          if(dis[x]+cost[x][y]<dis[y])
          {
             dis[y] = dis[x]+cost[x][y];
             if(!vis[y])
             {
                vis[y] = 1;
                Q.push(y);
             }
          }
       }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
           for(int j=1;j<=n;j++)
           {
               scanf("%d",&cost[i][j]);
           }
        }
        int ans,c1,cn;
        spfa(1);
        ans = dis[n];
        c1  = dis[1];//从1到1
        spfa(n);
        cn = dis[n];//从n到n
        ans = min(ans,c1+cn);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值