拓扑排序;
刚开始想的直接模拟,但没考虑到要是表达式里给的还没给出的边的话,就没法算呀。
看了吴永辉老师的题解,才明白是要进行拓扑排序,想想也很有道理,在我看来删边法最重要的三个部分:入度,邻接表,队列。
正好,这道题满足这三个条件,入度为零的点即为已知的点,压入队列中,对每个表达式项( i , j ),取出其中的每一项,计算其对应的行号 X 列号 Y ,(i,j)送入(x,y)的邻接表中,并累计(i,j)的入度。
从队列中取出入度为零的点,进行删边操作。同时给对应的边赋值,将过程中入度变为0的点压入队列中,往复直到队列为空。
这样的拓扑排序就构造成功。
code 如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
using namespace std;
int mmp[100][100];
struct point{
int x;
int y;
point(int a,int b):x(a),y(b){}
};
list<point> g[100][100];
int ind[100][100];
int main()
{
int n;
scanf("%d",&n);
while(n--){
char s[100];
int a,b;
scanf("%d%d",&a,&b);
memset(mmp,0,sizeof(mmp));
memset(ind,0,sizeof(ind));
for(int i=1;i<=b;i++){
for(int j=1;j<=a;j++){
scanf("%s",s);
if(s[0]=='='){
int ans=0;
char alpha[4];
char digit[4];
int j1=0,j2=0;
for(int k=1;s[k];k++){
if(isalpha(s[k])) alpha[j1++]=s[k];
else if(isdigit(s[k])) digit[j2++]=s[k];
else{
int col=0,row=0;
while((--j1)>=0){
int flag=26;
col=col*26+alpha[j1]-64;
}
while((--j2)>=0){
int flag=10;
row=row*10+digit[j2]-48;
}
ind[i][j]++;
point t(i,j);
g[row][col].push_back(t);
j1=j2=0;
}
}
int col=0,row=0;
while((--j1)>=0){
int flag=26;
col=col*26+alpha[j1]-64;
}
while((--j2)>=0){
int flag=10;
row=row*10+digit[j2]-48;
}
ind[i][j]++;
point t(i,j);
g[row][col].push_back(t);
}else mmp[i][j]=atoi(s);
}
}
queue<point> q;
for(int i=1;i<=b;i++){
for(int j=1;j<=a;j++){
if(ind[i][j]==0){
point t(i,j);
q.push(t);
}
}
}
while(!q.empty()){
point t=q.front();
q.pop();
for(list<point>::const_iterator it=g[t.x][t.y].begin();it!=g[t.x][t.y].end();it++){
mmp[it->x][it->y]+=mmp[t.x][t.y];
ind[it->x][it->y]--;
if(ind[it->x][it->y]==0){
q.push(point(it->x,it->y));
}
}
}
for(int i=1;i<=b;i++){
for(int j=1;j<=a;j++){
if(j!=1) printf(" ");
printf("%d",mmp[i][j]);
}
puts("");
}
for(int i=1;i<=b;i++){
for(int j=1;j<=a;j++){
if(!g[i][j].empty()) g[i][j].clear();
}
}
}
return 0;
}