zoukankan      html  css  js  c++  java
  • hdu 4370(最短路+思维)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4370

    题意:给出一个n×n的矩阵,求一个符合题意的n×n的只含有0和1的矩阵,使得两个矩阵位置对应的元素相乘后和最小。

    题意要求01矩阵:

    1. X12+X13+...+X1n=1

    2.X14+X24+...+X(n-1)n=1

    3.∑Xki (1<=k<=n)=∑Xij (1<=j<=n).(1<i<n)

    思路:将Xij看作点i到点j的路的花费,所以可以转换成一个图来作。而条件可以认为是

    1.点1出度为1,即一定有一条从点1出发的路。

    2.点n入度为1,即一定有一条到点n的路。

    3.其他点的出度入度相等。即一定有1到n的路或者有1自环和n自环。为什么?

    而求得的01矩阵乘以原矩阵,可以看作1为走这条路,0为不走。

    因为点1的出度为1(条件一),那么一定要到另一个点,如果是到点n即求一条最短路。否则到其他点,而其他点出入度要相同(条件三),这时需要这个点一定有出去的边,到n就有最短路,到1就有1自环,到其他点(最终都是要到1,n的)。而点n一定要有入度(条件二)则情况一样的,一定有1到n的路或则有n的自环。

    所以需要计算1到n的最短路,1自环和n自环的总值,两者最小就为答案,即计算一遍起点为1的d1[n],d1[1],再计算一遍起点为n的d2[n],ans=min(d1[n],d2[1]+d2[n]);

    值得注意的是这里的最短路写法(spfa)有点不一样,因为要算起点自环的花费,所以初始化d[strat]=inf,不能为d[strat]=0,这样第一遍更新找其他点到起点的距离d就更新不了。那么可以这样:自己更新第一次,手动将所有的点都加入队列即可。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=310;
    int map[maxn][maxn],d[maxn],visit[maxn];
    int n;
    
    void spfa(int u){
        queue<int> q;
        memset(visit,0,sizeof(visit));
        for(int i=1;i<=n;i++){//初始化 
            if(i==u)
                d[i]=inf;
            else{
                d[i]=map[u][i];
                q.push(i);//手动更新第一次找最短路 
                visit[i]=1;
            }
        }
        while(!q.empty()){
            int t=q.front();
            q.pop();
            visit[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(!visit[i]){
                        visit[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];//1到n的最短 
            int d1=d[1];//1自环 
            spfa(n);
            int d2=d[n];//n自环 
            printf("%d
    ",min(ans,d1+d2));
        }
        
        return 0;
    }
  • 相关阅读:
    windows下Yarn安装与使用(两种方法)
    git配置公钥---解决码云出现git@gitee.com: Permission denied (publickey)
    npm使用国内镜像的两种方法
    【LeetCode】33. Search in Rotated Sorted Array (4 solutions)
    【LeetCode】83. Remove Duplicates from Sorted List
    【LeetCode】82. Remove Duplicates from Sorted List II
    【LeetCode】85. Maximal Rectangle
    【LeetCode】84. Largest Rectangle in Histogram
    【LeetCode】87. Scramble String
    【LeetCode】162. Find Peak Element (3 solutions)
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10318440.html
Copyright © 2011-2022 走看看