您的位置:首页 > 其它

hdu 0 or 1(最短路spfa)(本质,抽象)

2017-02-27 13:47 387 查看
0 or 1

Problem Description

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.

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

ps:一看题直接懵圈了,完全没搞懂题目在说什么0.0 

题目是挺水的,但是关键是得搞懂啊

,要看透题目模型的本质

好吧,抽象一下吧

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).
    可以看成2~n-1号节点的出度等于入度

所以3个条件可以抽象为最短路中的两种情况

第一种A:
1号节点到n号节点的一条最短路径。Xij=1表示需要经过边(i,j),代价为Cij。Xij=0表示不需要经过边(i,j)。记最短路的花费为path

第二种B:
从1号节点出发走一个环再回到1(至少经过一个点,即不能是自环)的花费c1
从n号节点出发走一个环再回到n(同理)的花费c2
则符合条件的结果即为c1+c2

容易验证A||B为本题要求的充要条件
故最终答案为min(path,c1+c2)

代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

#define min(a,b)  (a<b?a:b)
#define maxn 300+10
const int inf=0x3f3f3f3f;

int d[maxn],cost[maxn][maxn];
bool inq[maxn];

void spfa(int st,int ed)
{
queue<int>q;
for(int i=1; i<=ed; i++)
{
if(i!=st)
{
d[i]=cost[st][i];
inq[i]=true;
q.push(i);
}
else
{
inq[i]=false;
d[i]=inf;
}
}
while(!q.empty())
{
st=q.front();
q.pop();
inq[st]=false;
for(int i=1; i<=ed; i++)
{
if(d[i]>d[st]+cost[st][i])
{
d[i]=d[st]+cost[st][i];
if(!inq[i])
{
inq[i]=true;
q.push(i);
}
}
}
}
}

int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&cost[i][j]);
spfa(1,n);
int s1=d
,s2=d[1];
spfa(n,n);
s2+=d
;
printf("%d\n",min(s1,s2));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: