首页 > 代码库 > ZOJ 3780 E - Paint the Grid Again 拓扑排序
ZOJ 3780 E - Paint the Grid Again 拓扑排序
https://vjudge.net/problem/49919/origin
题意:给你n*n只出现O和X的字符阵。有两种操作,一种操作Ri将i行全变成X,一种操作Ci将i列全变成O,每个不同的操作最多进行一次。现给出目标状态,求空盘下的字典序最小的操作顺序是怎样的。
思路:拿到题目看起来很复杂,但仔细读题会发现X和O只由特定操作出现,且操作只进行一次,那么单独地考虑每行每列,如i行中出现了O,且存在X(如果不存在X那么可以略去Ri操作),说明在Ri操作后进行了Cj的操作,同样的方法去考虑列,就能得到所有需要进行的行列操作相对顺序。这显然是个拓扑结构。那么将行操作或列操作看作点,建图拓扑排序即可。
关键还是在于建模,vijos上有道很相像的题目(1030),但比这道复杂一些还需要DFS。但是这道省赛题由于要求的复杂度不太严格,还可以模拟做。
但我居然一下子没有想出来用拓扑排序orz
weak-dish?
/** @Date : 2017-03-27-21.44 * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : */#include<bits/stdc++.h>#define LL long long#define PII pair#define MP(x, y) make_pair((x),(y))#define fi first#define se second#define PB(x) push_back((x))#define MMG(x) memset((x), -1,sizeof(x))#define MMF(x) memset((x),0,sizeof(x))#define MMI(x) memset((x), INF, sizeof(x))using namespace std;const int INF = 0x3f3f3f3f;const int N = 1e5+20;const double eps = 1e-8;const int ost = 510;char mp[510][510];vectorvt[1100];int fr[510], fc[510];int cnt[1100];int n;void init(){ MMF(fr); MMF(fc); MMF(cnt); for(int i = 0; i < n + ost; i++) vt[i].clear(); for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(mp[i][j] == ‘O‘) fc[j] = 1; else fr[i] = 1; } } for(int i = 0; i < n; i++) { if(!fr[i]) continue; for(int j = 0; j < n; j++) { if(mp[i][j] == ‘O‘) vt[i].PB(j + ost), cnt[j + ost]++; } } for(int j = 0; j < n; j++) { if(!fc[j]) continue; for(int i = 0; i < n; i++) { if(mp[i][j] == ‘X‘) vt[j + ost].PB(i), cnt[i]++; } }}void top(){ int ct = 0; priority_queue<int, vector, greater >q; for(int i = 0; i < n + ost; i++) { if(cnt[i] == 0 && vt[i].size() != 0) q.push(i); } while(!q.empty()) { int nw = q.top(); q.pop(); for(int i = 0; i < vt[nw].size(); i++) { int nt = vt[nw][i]; cnt[nt]--; if(!cnt[nt]) q.push(nt); } if(nw < ost) printf("%sR%d", ct==0?"":" ", nw + 1), ct = 1; else printf("%sC%d", ct==0?"":" ", nw - ost + 1), ct = 1; } if(ct == 0) printf("No solution"); printf("\n");}int main(){ int T; cin >> T; while(T--) { cin >> n; for(int i = 0; i < n; i++) { scanf("%s", mp[i]); } init(); top(); } return 0;}
ZOJ 3780 E - Paint the Grid Again 拓扑排序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。