LINK
题意:
给定
∑
i
=
1
n
∑
j
=
1
m
\sum_{i=1}^{n}\sum_{j=1}^{m}
∑i=1n∑j=1ma[i]<b[j],也就是所有ai和bj的关系我们是知道的,最后求最大值最小的构造方案,如果无解输出NO
思路:
先把相等的点用并查集维护一下,然后我们只维护<的关系,因为>反向建图就行了,然后跑拓扑DP,
f
[
i
]
>
=
∑
j
=
p
r
e
m
a
x
(
f
[
j
]
+
1
)
f[i]>=\sum_{j=pre}{max(f[j]+1)}
f[i]>=∑j=premax(f[j]+1)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int g[N>>1][N>>1];
int p[N];
int f[N];
vector<int>v[N];
vector<int>nv[N];
int d[N];
int q[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n+m;i++) p[i]=i,f[i]=1;
for(int i=1;i<=n;i++)
{
string s;
cin>>s;
int x=i;
int y;
for(int j=1;j<=m;j++){
y=j;
x=find(i);
y=find(j+n);
if(s[j-1]=='=')
{
p[x]=y;
}
else if(s[j-1]=='>')
{
//y->x;
v[j+n].push_back(i);
}
else
{
v[i].push_back(j+n);
}
}
}
for(int i=1;i<=n+m;i++){
for(auto j:v[i]){
if(find(i)==find(j)){
puts("No");
return 0;
}
nv[find(i)].push_back(find(j));
d[find(j)]++;
}
}
int hh=0;
int tt=-1;
int cnt=0;
int sz=0;
for(int i=1;i<=n+m;i++)
{
if(p[i]==i)
sz++;
}
// cout<<sz<<endl;
for(int i=1;i<=n+m;i++)
{
if(p[i]==i && !d[i])
q[++tt]=i;
}
// for(int i=1;i<=sz;i++)
// cout<<d[i]<<" ";
// cout<<endl;
while(hh<=tt){
auto td=q[hh++];
cnt++;
for(auto j:nv[td]){
// cout<<j<<" "<<d[j]<<endl;
f[j]=max(f[td]+1,f[j]);
if((--d[j])==0)
{
q[++tt]=j;
}
}
}
if(cnt==sz)
{
cout<<"Yes"<<endl;
for(int i=1;i<=n;i++)
cout<<f[find(i)]<<" ";
cout<<endl;
for(int i=n+1;i<=n+m;i++)
cout<<f[find(i)]<<" ";
}
else
cout<<"No"<<endl;
return 0;
}