您的位置:首页 > 运维架构

HDU 5195 DZY Loves Topological Sorting 拓扑排序

2016-04-23 15:04 295 查看

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5195

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=573&pid=1002

题解:

1、拓扑排序+贪心

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;

int n, m, k;

struct Node {
int v, flag;
Node(int v,int flag=0):v(v),flag(flag){}
Node() { flag = 0; }
};

vector<Node> head[maxn];
int ind[maxn],done[maxn];

void init() {
for (int i = 0; i < n; i++) {
ind[i] = done[i]=0;
head[i].clear();
}
}

int main() {
while (scanf("%d%d%d", &n, &m, &k) == 3 && n) {
init();
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v); u--, v--;
ind[v]++;
head[u].push_back(Node(v,0));
}

priority_queue<int> pq;

//删边
for (int i = n - 1; i >= 0; i--) {
if (k >= ind[i]) {
//将i的父亲ui中,满足ui<i,即边(ui,i)删了,这里要注意,对于边(ui,i),ui>i的边,根本不用删
k -= ind[i];
pq.push(i);
for (int j = 0; j < head[i].size(); j++) {
Node &nd = head[i][j];
if (i > nd.v) {
//把边(i,v)删了,拓扑排序的时候不能再走这条边了
nd.flag = 1;
ind[nd.v]--;
}
}
}
}

vector<int> ans;
//拓扑排序
while (!pq.empty()) {
int u = pq.top(); pq.pop();
if (done[u]) continue;
ans.push_back(u);
done[u] = 1;
for (int i = 0; i < head[u].size(); i++) {
Node& nd = head[u][i];
if (done[nd.v]||nd.flag) continue;
ind[nd.v]--;
if (ind[nd.v] == 0) pq.push(nd.v);
}
}

printf("%d", ans[0]+1);
for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]+1);
printf("\n");
}
return 0;
}
/*
5 3 1
4 3
1 3
3 2

5 3 0
4 3
1 3
3 2
*/


2、线段树+贪心

对于节点i,入度为ind[i],则可以这样贪心:对于1<=i<=n,求最大的i使得ind[i]<=k,我们可以把入度数组做成线段树,维护最小入度,二分查找,优先搜右边(右边的i会更大),找到以后,吧对于的子节点vj的入度减1,k-=ind[i]。这样一直做n次就能得到答案。

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#define lson (o<<1)
#define rson ((o<<1)+1)
#define M (l+(r-l)/2)
using namespace std;

const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;

int n, m, k;

vector<int> head[maxn];
int ind[maxn<<2],minv[maxn<<2];

int _pos, _v;
void update(int o, int l, int r) {
if (l==r) {
ind[o] += _v;
minv[o] = ind[o];
}
else {
if (_pos <= M) update(lson, l, M);
else update(rson, M + 1, r);
minv[o] = min(minv[lson], minv[rson]);
}
}

void query(int o, int l, int r,int &res) {
if (l == r) {
if (ind[o] <= k) {
k -= ind[o];
res = l;
}
}
else {
//printf("lson:%d,rson:%d\n",minv[lson],minv[rson]);
if (k >= minv[rson]) query(rson, M + 1, r,res);
else if (k >= minv[lson]) query(lson, l, M,res);
}
}

void init() {
for (int i = 1; i <= n; i++) head[i].clear();
memset(ind, 0, sizeof(ind));
memset(minv,0,sizeof(minv));
}

int main() {
while (scanf("%d%d%d", &n, &m, &k) == 3 && n) {
init();
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
head[u].push_back(v);
_pos = v, _v = 1;
update(1, 1, n);
}
//puts("after update");
vector<int> ans;
for (int i = 0; i < n; i++) {
int res;
query(1, 1, n, res);
//puts("after first qurey!");
//printf("res:%d\n", res);
ans.push_back(res);
for (int j = 0; j < head[res].size(); j++) {
_pos = head[res][j], _v = -1;
update(1, 1, n);
//puts("after first upate");
}
_pos = res, _v = INF;
update(1, 1, n);
}
//puts("ans is zero");
printf("%d", ans[0]);
for (int i = 1; i < ans.size(); i++) printf(" %d", ans[i]);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: