hdu 2807

http://acm.hdu.edu.cn/showproblem.php?pid=2807

题意:给n个m*m的矩阵,如果A*B=C,说明A到C有长度1的有向边。现要求任意点间的最短路。

思路:读完题会感觉是一个暴力的算法。但时间达到80^5,感觉过不了,随后看人家的解题报告,结果暴力都过了,数据有点水吧。但是后来自己写了个暴力,却超时了。人品呀~~~然后问队友,发现有优化的:如果A*B=C,则A*B*D=C*D,D为m*1的矩阵。设d=B*D,则A*B*D=A*d;同样设dd=A*d,cc=C*D;最后比较dd是否等cc就行了。

当然,D最好多取几个,以保证答案正确。

View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
using namespace std;
const int maxn = 81;
const int inf = 0xffffff;
int as[maxn][maxn][maxn];
int bs[maxn][maxn],cs[maxn][maxn];
int n,m;
void conect(int a,int b)
{
    int k,i,j,flag;
    int ds[maxn];
    for(i = 0; i < m; ++ i){
        ds[i] = 0;
        for(j = 0; j < m; ++ j)
            ds[i] += as[a][i][j] * cs[b][j];
    }
    for(k = 0; k < n; ++ k){
        if(k==a||bs[a][k]!=inf||k==b)continue;
        flag = 1;
        for(i = 0; i < m; ++ i){
            if(!flag)break;
            if(cs[k][i]^ds[i])flag = 0;
        }
        if(flag)bs[a][k] = 1;
    }
}
bool readin()
{
    int i,j,k;
    scanf("%d %d",&n,&m);
    if(n+m==0)return false;
    for(k = 0; k < n; ++ k)
    for(i = 0; i < m; ++ i){
        cs[k][i] = 0;
        for(j = 0; j < m; ++ j){
            scanf("%d",&as[k][i][j]);
            cs[k][i] += as[k][i][j];
        }
    }
    for(i = 0; i < n; ++ i){
        for(j = 0; j < n; ++ j)
        bs[i][j] = inf;
        bs[i][i] = 0;
    }
    for(i = 0; i < n; ++ i)
    for(j = 0; j < n; ++ j)
    if(i^j)conect(i,j);
    return true;
}
void flody()
{
    int i,j,k;
    for(k = 0; k < n; ++ k)
    for(i = 0; i < n; ++ i){
        if(i==k || bs[i][k]==inf)continue;
        for(j = 0; j < n; ++ j)
        if(k==j||i==j||bs[k][j]==inf)continue;
        else if(bs[i][k] < bs[i][j] - bs[k][j])
        bs[i][j] = bs[i][k] + bs[k][j];
    }
}
int main()
{
    int q,a,b;
    while(readin()){
        flody();
        scanf("%d",&q);
        while(q--){
            scanf("%d %d",&a,&b);
            --a; --b;
            if(bs[a][b]==inf)
                puts("Sorry");
            else
                printf("%d\n",bs[a][b]);
        }
    }
    return 0;
}

这个题也是一样的做法:

http://judge.lavida.us/1582

View Code
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxn = 1005;
int as[maxn][maxn],cs[maxn];
int n,flag;
bool readin()
{
    int i,j,k,t,tt;
    if(scanf("%d",&n)==EOF)return false;
    if(!n)return false;
    flag = 1;
    for(i = 0; i < n; ++ i){
        cs[i] = 0;
        for(j = 0; j < n; ++ j){
            scanf("%d",&as[i][j]);
            cs[i] += as[i][j] * (j + 1);
        }
    }
    for(i = 0; i < n; ++ i){
        t = tt = 0;
        for(j = 0; j < n; ++ j){
            scanf("%d",&k);
            t += k * (j + 1);
            tt += cs[j] * as[i][j];
        }
        if(t ^ tt) flag = 0;
    }return true;
}
int main()
{
    while(readin()){
        if(flag)puts("YES");
        else puts("NO");
    }
    return 0;
}

posted on 2012-08-10 18:35  aigoruan  阅读(172)  评论(0)    收藏  举报

导航