SWERC 2019-20 G - Swapping Places
作者:互联网
题意:给定S种动物,L个朋友关系,规定相邻的朋友可以交换位置,求排成一行的n个动物通过交换可以获得的最小字典序列
分析:发现不是朋友的动物之间相对位置无法改变,构成拓扑序,对于那些可以改变的,在拓扑排序的时候放进优先队列求字典序最小就行了
如何建图:对于第i个动物,只需要知道S种动物在它之前出现的位置,如果同一种动物在它之前出现多次,只需要记录最后一次的位置(即保证相对位置不改变),然后判断是否为朋友,如不是建立一条有向边,入度+1
#include<bits/stdc++.h>
using namespace std;
#define fr first
#define se second
#define et0 exit(0);
#define rep(i, a, b) for(int i = (a); i <= (b); i ++)
#define rrep(i, a, b) for(int i = (a); i >= (b); i --)
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
typedef unsigned long long ULL;
const int INF = 0X3f3f3f3f, N = 200 + 10, M = 1e5 + 10, MOD = 1e9 + 7;
const double eps = 1e-7;
int S, L, n;
string a[N], b[M];
int st[N][N];
int pos[M], last[N];
string ans[M];
unordered_map<string, int> msi;
int idx, head[M];
int in[M];
struct EDGE {
int to, next;
} eg[200 * M];
void add(int x, int y) {
eg[++idx].to = y;
eg[idx].next = head[x];
head[x] = idx;
}
void topo() {
priority_queue<PII, vector<PII>, greater<PII> > q;
rep(i, 1, n)
if (!in[i]) q.push({msi[b[i]], i});
int cnt = 0;
while (!q.empty()) {
PII cur = q.top();
ans[++cnt] = b[cur.se];
q.pop();
for (int i = head[cur.se]; ~i; i = eg[i].next) {
int to = eg[i].to;
in[to]--;
if (!in[to]) q.push({msi[b[to]], to});
}
}
}
void work() {
cin >> S >> L >> n;
rep(i, 1, S) cin >> a[i];
sort(a + 1, a + 1 + S);
rep(i, 1, S) msi[a[i]] = i;
rep(i, 1, L) {
string x, y;
cin >> x >> y;
st[msi[x]][msi[y]] = st[msi[y]][msi[x]] = 1;
}
memset(head, -1, sizeof head);
memset(last, -1, sizeof last);
rep(i, 1, n) cin >> b[i];
rep(i, 1, n) {
rep(j, 1, S)
if (last[j] == -1 || st[msi[b[i]]][j]) continue;
else {
add(last[j], i);
in[i]++;
}
last[msi[b[i]]] = i;
}
topo();
rep(i, 1, n) cout << ans[i] << " ";
cout << endl;
}
signed main() {
work();
return 0;
}
标签:head,20,int,rep,2019,msi,last,SWERC,eg 来源: https://www.cnblogs.com/xhy666/p/16456174.html