D. Gourmet choice
题意:给出两个序列
a
i
a_i
ai和
b
j
b_j
bj的大小关系,问能否恢复这两个序列,如果可以则输出,否则输出
N
o
No
No。
题解:因为有等于号的存在,所以导致建图会形成环,因此我们考虑用并查集将等于关系的缩成一个点,然后去建图,跑一遍拓扑即可。
代码
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
#define P pair<int,int>
using namespace std;
int a[2010], f[2020], in[2010], ans[2010];
vector<int> E[2010];
int getf(int v)
{
if(f[v] == v) return v;
return f[v] = getf(f[v]);
}
void mrg(int u,int v)
{
int p = getf(u);
int q = getf(v);
if(p != q) f[p] = q;
}
void addEdge(int u,int v)
{
E[u].push_back(v);
in[v]++;
}
bool topsort(int n)
{
queue<P> q;
for(int i = 1; i <= n; ++i) if(!in[i]) q.push(P(i,1));
while(!q.empty()) {
P cur = q.front(); q.pop();
ans[cur.first] = cur.second;
for(auto v : E[cur.first]) {
if(--in[v] == 0) q.push(P(v,cur.second + 1));
}
}
for(int i = 1; i <= n; ++i) {
if(!(ans[i] = ans[getf(i)])) return 0;
}
return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
for(int i = 0; i < 2010; ++i) f[i] = i;
cin >> n >> m;
string s[1020];
for(int i = 0; i < n; ++i)
cin >> s[i];
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
if(s[i - 1][j - 1] == '=') mrg(i, n + j);
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
if(s[i - 1][j - 1] == '>') {
if(getf(i) != getf(n + j)) {
addEdge(getf(n + j), getf(i));
}else{
return cout << "No\n",0;
}
}else if(s[i - 1][j - 1] == '<') {
if(getf(i) != getf(n + j)) {
addEdge(getf(i), getf(n + j));
}else{
return cout << "No\n",0;
}
}
}
}
if(topsort(n + m)) {
cout << "Yes" << endl;
for(int i = 1; i <= n + m; ++i) {
cout << ans[i] << (((i == n)||(i == n + m)) ? '\n' : ' ');
}
}else{
cout << "No" << endl;
}
return 0;
}
F. Asya And Kittens
题意:每次合并相邻的两个集合,然后输出最后的序列。
题解:明显并查集了,但是考虑到每次必须合并的是相邻的两个集合,即有位置关系,需要启发式合并,将集合小的放到集合大的下面,因此我们用链表来维护一个集合,每次合并的时候根据大小将两个链表
s
p
l
i
c
e
splice
splice连接一下就好了。
代码
#include<bits/stdc++.h>
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
using namespace std;
const int N = 150100;
int f[N],n;
list<int> lis[N];
int getF(int v)
{
if(f[v] == v) return f[v];
return f[v] = getF(f[v]);
}
void merge1(int u,int v)
{
int t1 = getF(u);
int t2 = getF(v);
if(t1 != t2) {
if(lis[t1].size() > lis[t2].size()) {
f[t2] = t1;
lis[t1].splice(lis[t1].end(),lis[t2]);
}else {
f[t1] = t2;
lis[t2].splice(lis[t2].end(),lis[t1]);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
int x,y;
for(int i = 0; i <= n; ++i) {
f[i] = i;
lis[i].push_back(i);
}
for(int i = 0; i < n; ++i) {
cin >> x >> y;
merge1(x,y);
}
int rt = getF(1);
for(auto &v : lis[rt]) {
cout << v << ' ';
}
return 0;
}