D. Gourmet choice
http://codeforces.com/contest/1131/problem/D
给你一个n*m的图,上面只有 <,>,=
代表第一组的第i个人与第二组的第j个人的得分大小比较
请你输出每个人能够得到的最小成绩
不可以输出NO
因为有比分相等的情况,我们就把他当做一个点进行缩点,使用并查集
比分不等时,我们建立拓扑图,比如,ai>bj,让bj向ai建边,ai的入度增加
这样子,入度为0的点,就是起点,这里要注意判断,要是没有入度为0的点,就要输出NO
从起点开始,最低分数是1,之后走的点,进行拓扑
if(!ans[v]) ans[v]=ans[u]+1;
else ans[v]=max(ans[u]+1,ans[v]);
如果不是所有的点都被走过,那么还是要输出No
#include <bits/stdc++.h>
using namespace std;
char a[1005][1005];
vector <int> G[2010];
int fa[2010],du[2010];
int ans[2010];
int Find(int x)
{
if(x==fa[x]) return x;
else return fa[x]=Find(fa[x]);
}
int main()
{
queue <int> q;
int n,m,num=0;
cin>>n>>m;
for(int i=1;i<=2008;i++)
{
fa[i]=i;
}
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]+1);
for(int j=1;j<=m;j++)
{
if(a[i][j]=='=')
{
int fx=Find(i),fy=Find(j+1000);
if(fx!=fy)
{
num++;
fa[fx]=fy;
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x=Find(i),y=Find(j+1000);
if(a[i][j]=='=') continue;
else
{
if(a[i][j]=='>')
{
G[y].push_back(x);
du[x]++;
}
else
{
G[x].push_back(y);
du[y]++;
}
}
}
}
for(int i=1;i<=n;i++)
{
if(fa[i]==i&&du[i]==0)
{
ans[i]=1;
num++;
q.push(i);
}
}
for(int i=1001;i<=m+1000;i++)
{
if(fa[i]==i&&du[i]==0)
{
ans[i]=1;
num++;
q.push(i);
}
}
if(q.empty())
{
printf("NO\n");
return 0;
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!ans[v]) ans[v]=ans[u]+1;
else ans[v]=max(ans[u]+1,ans[v]);
du[v]--;
if(!du[v])
{
num++;
q.push(v);
}
}
}
if(num!=n+m)
{
printf("NO\n");
return 0;
}
printf("YES\n");
for(int i=1;i<=n;i++)
{
int x=Find(i);
printf("%d ",ans[x]);
}
cout<<endl;
for(int i=1001;i<=m+1000;i++)
{
int x=Find(i);
printf("%d ",ans[x]);
}
return 0;
}