• 0 or 1 HDU


    题目描述

    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.

    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.

    题目大意:给你一个n*n 的矩阵,让你找出一个满足上述条件的矩阵,使得这两个矩阵每个相同位置相乘的总和最小。

    解题思路: 由于在最短路专题做到,可以看出这道题就是把题意转化为最短路的思想。

           把要让我们写出的矩阵看成n个点的邻接矩阵。

           观察让我们写出的矩阵: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)    可以看成其它点入度和出度相等

           输入的矩阵即是这n个点相互之间的花费,因此让我们求的就是,1~n的最小花费或者是1的环加上n的环的最小花费。

           答案就是这两者的最小值。

           spfa的有一种操作是可以求单源最小环的,即初始化dis[start] = INF,且一开始让源点之外的点入队

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define MOD 998244353 
    #define INF 0x3f3f3f3f
    #define mem(a,x) memset(a,x,sizeof(a))  
    #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    int mp[305][305];
    int n;
    int dis[305];
    bool vis[305];
    
    void spfa(int start)
    {
        queue<int>Q;
        for(int i=1;i<=n;i++){
           dis[i]=mp[start][i];
           if(i!=start){
              Q.push(i);
              vis[i]=true;
           }else{
              vis[i]=false;
           }
        }
        dis[start]=INF;
    
        while(!Q.empty())
        {
            int u=Q.front();
            Q.pop();
            vis[u]=false;
            for(int i=1;i<=n;i++){
                if(i==u)continue;
                if(dis[i]>dis[u]+mp[u][i]){
                   dis[i]=dis[u]+mp[u][i];
                   if(!vis[i]){
                      Q.push(i);
                   }
                }
            }
        }
    }
    
    int main()
    {
       while(~scanf("%d",&n)){
       for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
              scanf("%d",&mp[i][j]);
          }
       }
       spfa(1);
       int num1=dis[n];
       int num2=dis[1];
       spfa(n);
       int num3=dis[n];
       cout<<min(num1,num2+num3)<<endl;
     }
       return 0;
    }
    越自律,越自由
  • 相关阅读:
    信息安全系统设计基础第二周学习总结
    java实验报告五
    java实验报告三
    java实验报告二
    java实验报告一
    mysql
    C语言理论知识
    数据存储与输出输入
    软件开发概述 编程语言概述
    C语言 常用单词
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13435564.html
Copyright © 2020-2023  润新知