HDU4370(思维最短路径)

Problem Description
Given a nn matrix Cij (1<=i,j<=n),We want to find a nn 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.
Hint

For sample, X12=X24=1,all other Xij is 0.

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.

Sample Input
4
1 2 4 10
2 0 1 1
2 2 0 5
6 3 1 2

Sample Output
3

Author
Snow_storm

Source
2012 Multi-University Training Contest 8

题意:
给你一个二维矩阵让你创建一个新的二维矩阵X使得:
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).
求 ∑Cij*Xij(1<=i,j<=n)最小值

题解:
可以把这个矩阵看成一个有向图条件1和条件2 表示定点1的出度为1 定点n的入度为1
其他点的入度与出度相等
就可以转化为二种可能:
1:求1到n的最短距离
2:1和n都分别各自组成一个环求这个两个环上的边和
答案:去上面的最小值

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a))
#define il       inline
#define eb(a)    emplace_back (a)
#define pb(a)    push_back(a)
typedef long long ll;
const int maxn=310+2;
const int minn=100+4;
const int inf=0x3f3f3f3f3f;
int n,vis[maxn],dis[maxn],mat[maxn][maxn];
queue<int> qu;
il void  spfa(int a)
{
    clr(vis,0);
    for(int i=1;i<=n;++i)//预处理到每个定点的值因为要求a到a环的大小
    {
        if(i!=a)
        {
            qu.emplace(i);
            vis[i]=1;
            dis[i]=mat[a][i];
        }
    }
    dis[a]=inf;
    while(!qu.empty())
    {
        int nu=qu.front();qu.pop();vis[nu]=0;
        for(int i=1;i<=n;++i)
        {
            if(i==nu){continue;}//因为再当中到其本身是木有意义的
            int tv=mat[nu][i];
            if(dis[i]>dis[nu]+mat[nu][i])
            {
                dis[i]=dis[nu]+mat[nu][i];
                if(!vis[nu])
                {
                    vis[i]=1;
                    qu.emplace(i);
                }
            }
        }
    }
    return ;
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            {
                scanf("%d",&mat[i][j]);
            }
        }
        spfa(1);
        int ans=dis[n];
        int res1=dis[1];
        spfa(n);
        int res2=dis[n];
        printf("%d\n",min(ans,res1+res2));//输出两个中最小的那个
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值