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

hdu 5195 DZY Loves Topological Sorting

2015-03-29 15:20 330 查看
问题描述
一张有向图的拓扑序列是图中点的一个排列,满足对于图中的每条有向边(u→v) 从 u 到 v,都满足u在排列中出现在v之前。
现在,DZY有一张有向无环图(DAG)。你要在最多删去k条边之后,求出字典序最大的拓扑序列。

输入描述
输入有多组数据。 (TestCase≤5)
第一行,三个正整数 n,m,k(1≤n,m≤105,0≤k≤m).
接下来m行,每行两个正整数 u,v(u≠v,1≤u,v≤n), 代表一条有向边(u→v).

输出描述
对于每组测试数据,输出一行字典序最大的拓扑序列。

输入样例
5 5 2
1 2
4 5
2 4
3 4
2 3
3 2 0
1 2
1 3

输出样例
5 3 1 2 4
1 3 2

Hint
数据1. 删除(2->3),(4->5)两条边,可以得到字典序最大的拓扑序列:(5,3,1,2,4).


分析:刚看这题想了想,不就是拓扑排序+优先队列吗,只不过多了个删边。刚开始想的是,从最大的点开始删边,能删就删,删完边后再拓扑排序,写完一交果断WA。直到比赛结束,都没过。。。

后来想了想,应该在每一步拓扑排序的时候进行删边,如果存在一个点,将其入边全部删除以后,能改变当前拓扑排序的结果,即那个点比当前优先队列最大的元素还大,那么就将其入边都删掉,然后入队。交上去后超时了。。。因为我是顺序查找的最大元素,所以存在很多无用的查找。

最后我用一个set来保存,当前未入过队的元素,然后在里面找最大的点,查找的过程中如果发现某个点,已经入过队了,那么将其删除。终于AC- -。

一个简单的贪心+拓扑排序都没做出来,还是太弱了啊。。。。。。。。。。。。。

vector实现邻接表: 717MS

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 100005;

struct graph{
vector<int> list[maxn];
int in[maxn];
int n;//n个顶点
int m;//m条边

graph(){}

void clear(){
for(int i = 0; i <= n; i++){
list[i].clear();
in[i] = 0;
}
}
};

struct set_node{
int x;

set_node(int _x){
x = _x;
}

bool operator < (const set_node &b) const{
return x > b.x;
}
};

int k;
graph g;
int res[maxn];

void input(){
int u,v;
g.clear();
for(int i = 0; i < g.m; i++){
scanf("%d%d",&u,&v);
g.list[u].push_back(v);
g.in[v]++;
}
}

void solve(){
priority_queue<int> q;
set<set_node> s;

for(int i = 1; i <= g.n; i++){
if(g.in[i] == 0) q.push(i);
else s.insert(set_node(i));
}

for(int i = 1; i <= g.n; i++){//topsort
//
set<set_node>::iterator it;
if(k > 0)
for(it = s.begin(); it != s.end();){
int p = it->x;
if(p < q.top()) break;

if(g.in[p] > 0 && g.in[p] <= k){
k -= g.in[p];
g.in[p] = 0;
q.push(p);
break;
}

if(g.in[p] <= 0 ) {
set<set_node>::iterator itt = it;
it++;
s.erase(itt);
}
else it++;

}
int u = q.top(); q.pop();
g.in[u]--; res[i] = u;

for(int i = 0; i < g.list[u].size(); i++){
int v = g.list[u][i];
if(--g.in[v] == 0) q.push(v);
}

}//end of topsort

printf("%d",res[1]);
for(int i = 2; i <= g.n; i++) printf(" %d",res[i]);
printf("\n");

}

int main(){
while(scanf("%d%d%d",&g.n,&g.m,&k) == 3){
input();
solve();
}
return 0;
}


静态链实现邻接表:639MS

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <map>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 100005;

struct edge{
int v;
int next;
};

struct graph{
int list[maxn];
edge arc[maxn];
int cnt;
int in[maxn];
int n;//n个顶点
int m;//m条边

graph(){}

void clear(){
for(int i = 0; i <= n; i++){
list[i] = -1;
in[i] = 0;
}
cnt = 0;
}

void add(int u, int v){
arc[cnt].v = v;
arc[cnt].next = list[u];
list[u] = cnt;
cnt++;
}
};

struct set_node{
int x;

set_node(int _x){
x = _x;
}

bool operator < (const set_node &b) const{
return x > b.x;
}
};

int k;
graph g;
int res[maxn];

void input(){
int u,v;
g.clear();
for(int i = 0; i < g.m; i++){
scanf("%d%d",&u,&v);
g.add(u,v);
g.in[v]++;
}
}

void solve(){
priority_queue<int> q;
set<set_node> s;

for(int i = 1; i <= g.n; i++){
if(g.in[i] == 0) q.push(i);
else s.insert(set_node(i));
}

for(int i = 1; i <= g.n; i++){//topsort
//
set<set_node>::iterator it;
if(k > 0)
for(it = s.begin(); it != s.end();){
int p = it->x;
if(p < q.top()) break;

if(g.in[p] > 0 && g.in[p] <= k){
k -= g.in[p];
g.in[p] = 0;
q.push(p);
break;
}

if(g.in[p] <= 0 ) {
set<set_node>::iterator itt = it;
it++;
s.erase(itt);
}
else it++;

}
int u = q.top(); q.pop();
g.in[u]--; res[i] = u;

for(int i = g.list[u]; i != -1; i = g.arc[i].next){
int v = g.arc[i].v;
if(--g.in[v] == 0) q.push(v);
}

}//end of topsort

printf("%d",res[1]);
for(int i = 2; i <= g.n; i++) printf(" %d",res[i]);
printf("\n");

}

int main(){
while(scanf("%d%d%d",&g.n,&g.m,&k) == 3){
input();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: