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最好多取几个,以保证答案正确。

#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; }
这个题也是一样的做法:

#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; }