HDU 4370 0 or 1

题意: 给定n * n矩阵C ij(1 <= i,j <= n),我们要找到0或1的n * n矩阵X ij(1 <= i,j <= n)。
此外,X ij满足以下条件:
1.X 12 + X 13 + … X 1n = 1
2.X 1n + X 2n + … X n-1n = 1
3.对于每个i(1 <i <n),满足ΣXki(1 <= k <= n)=ΣXij(1 <= j <= n)。
例如,如果n = 4,我们可以得到以下等式:
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
现在,我们想知道你可以得到的最小ΣCij * X ij(1 <= i,j <= n)。
题解:
我们可以将Xij看成点i到点j是否连了一条单向道路,Cij表示i到j这条路的权值。
由此,第一个条件可以变成:点1的出度为1。
第二个条件:点n的入度为1
第三个条件:其他点的出度和入度是相等的。
由此题目所要求的就转化为比较点1的自环+点n的自环和点1到点n的最短路的大小,取最小值。
代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int MAXN=1e3;
int map[MAXN][MAXN],d[MAXN],vis[MAXN];
int n;
void spfa(int u)
{
    
    
    queue<int> q;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
    
    
        if(i==u)
            d[i]=inf;
        else
        {
    
    
            d[i]=map[u][i];
            q.push(i); 
            vis[i]=1;
        }
    }
    while(!q.empty())
    {
    
    
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(int i=1;i<=n;i++)
        {
    
    
            if(d[i]>d[t]+map[t][i])
            {
    
    
                d[i]=d[t]+map[t][i];
                if(!vis[i])
                {
    
    
                    vis[i]=1;
                    q.push(i);
                }
            }
        }
    }
}

int main(){
    
    
    while(scanf("%d",&n)!=EOF)
    {
    
    
        for(int i=1;i<=n;i++)
        {
    
    
            for(int j=1;j<=n;j++)
                scanf("%d",&map[i][j]);
        } 
        spfa(1);
        int ans=d[n];
        int d1=d[1]; 
        spfa(n);
        int d2=d[n];
        printf("%d\n",min(ans,d1+d2));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45755679/article/details/108606938