题意:
有两个数组a[],b[],分别由n个和m个
然后给你一个n*m的矩阵
mp[i,j]='>' 表示a[i]>b[j]
mp[i,j]='=' 表示a[i]=b[j]
mp[i,j]='<' 表示a[i]<b[j]
让你输出满足条件的答案,并且这组答案要是所有元素最大值最小的那组
解析:
这道题....又脑子挂了..一直在比较同一组元素的大小..虽然最后做出来了...但花了两个小时....
我的思路就是先把b[]排出来,根据‘>’ b[j]--,'=' b[j]+=0 ,'<' b[j]++
把b[]都增大1000倍,好计算下面的a[]
然后再根据排出来的b[],来算a[],注意这里因为会有No的情况,
所以在这个过程中,你可能找不到满足条件的a[i],那么这个时候直接输出No就可以了...
之前就一直在纠结怎么判断No....只要先算出来解,在回去判断就可以了..
那么最后把a,b合并,离散化输出
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
char mp[N][N];
int sec[N],fir[N];
int num[3];
int b[N+N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
getchar();
scanf("%s",mp[i]+1);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='>') sec[j]--;
else if(mp[i][j]=='<') sec[j]++;
}
}
int flag=1;
for(int j=1;j<=m;j++)
sec[j]*=1000;
for(int i=1;i<=n;i++)
{
num[0]=num[1]=INF; //'=','<','>'
num[2]=-INF;
for(int j=1;j<=m;j++)
{
if(mp[i][j]=='=')
{
if(num[0]==INF) num[0]=sec[j];
else if(num[0]!=sec[j]) flag=0;
}
else if(mp[i][j]=='<')
{
num[1]=min(sec[j],num[1]);
}
else
{
num[2]=max(sec[j],num[2]);
}
}
if(!flag) break;
if(num[2]>=num[1]) flag=0;
else if(num[0]!=INF)
{
if(num[0]<num[1]&&num[0]>num[2])
fir[i]=num[0];
else
flag=0;
}
else
fir[i]=num[2]+1;
if(!flag) break;
}
if(flag){
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(fir[i]>sec[j])
{
if(mp[i][j]!='>') {flag=0;break;}
}
else if(fir[i]==sec[j])
{
if(mp[i][j]!='=') {flag=0;break;}
}
else
{
if(mp[i][j]!='<') {flag=0;break;}
}
}
if(!flag) break;
}
int tot=0;
for(int i=1;i<=n;i++) b[++tot]=fir[i];
for(int j=1;j<=m;j++) b[++tot]=sec[j];
sort(b+1,b+1+tot);
int cnt=unique(b + 1, b + tot + 1) - b - 1;
for(int i=1;i<=n;i++)
fir[i]=lower_bound(b+1,b+1+cnt,fir[i])-b;
for(int j=1;j<=m;j++)
sec[j]=lower_bound(b+1,b+1+cnt,sec[j])-b;
}
if(!flag) printf("No\n");
else
{
printf("Yes\n");
for(int i=1;i<=n;i++)
if(i==1) printf("%d",fir[i]);
else printf(" %d",fir[i]);
printf("\n");
for(int j=1;j<=m;j++)
if(j==1) printf("%d",sec[j]);
else printf(" %d",sec[j]);
printf("\n");
}
}
不过上面的做法太烦了...这道题其实就是一道拓扑排序的裸题....
mp都给你了,只要把里面的相等的一对数,归到一个并查集,然后根据'<' '>'建边
然后拓扑排序一遍就可以了
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int N = 2e3+10;
typedef pair<int,int> PII;
char mp[N][N];
int fa[N];
int num[N];
int deg[N],tot;
vector<int> Less_than[N]; //More_than
int findfa(int x)
{
if(x==fa[x]) return fa[x];
int nex=fa[x];
fa[x]=findfa(nex);
return fa[x];
}
inline void unite(int x,int y)
{
int fx,fy;
fx=findfa(x);
fy=findfa(y);
if(fx!=fy) fa[fx]=fy;
}
queue<PII> mq;
void toposort()
{
for(int i=1;i<=tot;i++)
if(!deg[i]&&findfa(i)==i) mq.push(make_pair(i,1)),num[i]=1;
while(!mq.empty())
{
PII u=mq.front();
mq.pop();
for(auto x:Less_than[u.first])
{
deg[x]--;
if(!deg[x])
{
num[x]=u.second+1;
mq.push(make_pair(x,num[x]));
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
tot=n+m;
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for(int i=1;i<=tot;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(mp[i][j]=='=') unite(i,n+j);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
if(mp[i][j]=='<')
Less_than[findfa(i)].push_back(findfa(n+j)),deg[findfa(n+j)]++;
else if(mp[i][j]=='>')
Less_than[findfa(n+j)].push_back(findfa(i)),deg[findfa(i)]++;
}
memset(num,-1,sizeof(num));
toposort();
int flag=1;
for(int i=1;i<=tot;i++)
{
if(i==findfa(i)&&num[i]==-1)
{flag=0;break;}
}
if(!flag) printf("No\n");
else
{
printf("Yes\n");
for(int i=1;i<=n;i++)
{
if(i>1) printf(" ");
printf("%d",num[findfa(i)]);
}
printf("\n");
for(int i=1;i<=m;i++)
{
if(i>1) printf(" ");
printf("%d",num[findfa(n+i)]);
}
printf("\n");
}
}