HDU-4370 0 or 1

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

条件1说明V1出度为1
条件2说明Vn入读为1
条件3说明Vi , (2 <= i <= n-1 ) 入度等于出度
三个条件 <=> 有一条从V1到Vn存在一条路径这样就使得条件1,2,3满足,当然这是充分条件,
还有一种特殊情况,就是V1和Vn都有一条长度大于1的自环,同样能使1,2,3成立。

#include<bits/stdc++.h>
using namespace std;
int dis[303],n,mmp[303][303];
bool in[303];
queue<int>que;
void SPFA(int s,int &loop) {
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(in,0,sizeof(in));
    loop=0x3f3f3f3f;
    dis[s]=0;
    in[s]=1;
    que.push(s);
    while(!que.empty()) {
        int x=que.front();
        que.pop();
        in[x]=0;
        for(int j=1; j<=n; ++j) {
            if(j==s&&x!=s) {
                loop=min(loop,mmp[x][j]+dis[x]);
            }
            if(dis[x]+mmp[x][j]<dis[j]) {
                dis[j]=dis[x]+mmp[x][j];
                if(!in[j]) {
                    que.push(j);
                    in[j]=1;
                }
            }
        }
    }
}
int main() {
    freopen("in.txt","r",stdin);
    while((scanf("%d",&n))==1) {
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                scanf("%d",&mmp[i][j]);
        int loop1;
        //第一遍SPFA求得最短路径和V1的长度大于1的最短自环
        SPFA(1,loop1);
        int ans=dis[n];
        int loop2;
        //第二遍求Vn的长度大于1的最短自环
        SPFA(n,loop2);
        cout<<min(ans,loop1+loop2);
    }
    return 0;
}
posted @ 2020-12-16 17:02  肆之月  阅读(102)  评论(0编辑  收藏  举报