您的位置:首页 > 其它

hdu 5195 求最大拓扑序列 拓扑+贪心

2015-03-29 22:48 260 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5195

题意:给出一个DAG,求删除一定边后,尽可能使输出的拓扑序列尽可能大。

题意很明显,只要用拓扑和贪心就可以了,易错点请看:http://blog.csdn.net/u013508213/article/details/44726495

这题应主要就是拓扑排序的应用,可惜不会拓扑,遗憾。

PS:此题又出现了C++ AC,但是G++TLE。。。。。

代码:

#include<iostream>
#include<sstream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<set>
#define LL __int64
#define maxn 100010

using namespace std;

struct node{//前向星存储边
int to[maxn],front[maxn],last[maxn],tot;
void clear(){
memset(to,0,sizeof(to));memset(front,0,sizeof(front));
memset(last,0,sizeof(last));tot=0;
}
void add(int u,int v){
to[++tot]=v;front[tot]=last[u];last[u]=tot;
}
}G;

int n,m,k;
int deg[maxn];
int vis[maxn];
int vis2[maxn];

void topsort(){
memset(vis,0,sizeof(vis));
priority_queue<int> Q;
for(int i=1;i<=n;i++) if(deg[i]<=0) Q.push(i),vis[i]=1;
int cnt=0;
while(!Q.empty()){//不断让度为0的点入队,出队时同时更新为入队的度
int tp=Q.top();
printf("%d%c",tp,(++cnt)==n? '\n':' ');
Q.pop();
if(vis2[tp]) continue;//在main中已经更新其后继点
tp=G.last[tp];
while(tp){//更新其后继点的度
if(vis[G.to[tp]]){tp=G.front[tp];continue;}
deg[G.to[tp]]--;
if(deg[G.to[tp]]==0) Q.push(G.to[tp]),vis[G.to[tp]]=1;
tp=G.front[tp];
}
}
}

int main(){
//freopen("D:\\in.txt","r",stdin);
//freopen("D:\\out.txt","w",stdout);
while(cin>>n)
{
cin>>m>>k;
memset(deg,0,sizeof(deg));
memset(vis2,0,sizeof(vis2));
G.clear();
int u,v;
for(int i=0;i<m;i++){
scanf("%d %d",&u,&v);
deg[v]++;G.add(u,v);
}
for(int i=n;i>=1;i--)
if(k<=0) break;
else if(k>=deg[i]) {//模拟贪心的删边顺序
int t=G.last[i];
while(t) {deg[G.to[t]]--;t=G.front[t];}//更新删除该节点后继的的度
vis2[i]=1;
k-=deg[i],deg[i]=0;
}
topsort();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: