码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5195 线段树+拓扑

时间:2015-11-10 20:55:05      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:

DZY Loves Topological Sorting

 

Problem Description
A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge (uv)技术分享 from vertex u技术分享 to vertex v技术分享 , u技术分享 comes before v技术分享 in the ordering.
Now, DZY has a directed acyclic graph(DAG). You should find the lexicographically largest topological ordering after erasing at most k技术分享 edges from the graph.
 

 

Input
The input consists several test cases. (TestCase5技术分享 )
The first line, three integers n,m,k(1n,m10技术分享5技术分享,0km)技术分享 .
Each of the next m技术分享 lines has two integers: u,v(uv,1u,vn)技术分享 , representing a direct edge(uv)技术分享 .
 

 

Output
For each test case, output the lexicographically largest topological ordering.
 

 

Sample Input
5 5 2 1 2 4 5 2 4 3 4 2 3 3 2 0 1 2 1 3
 

 

Sample Output
5 3 1 2 4 1 3 2
Hint
Case 1. Erase the edge (2->3),(4->5). And the lexicographically largest topological ordering is (5,3,1,2,4).
 
题解:因为我们要求最后的拓扑序列字典序最大,所以一定要贪心地将标号越大的点越早入队。我们定义点ii的入度为d_id?i??。假设当前还能删去kk条边,那么我们一定会把当前还没入队的d_i\leq kd?i??k的最大的ii找出来,把它的d_id?i??条入边都删掉,然后加入拓扑序列。可以证明,这一定是最优的。

具体实现可以用线段树维护每个位置的d_id?i??,在线段树上二分可以找到当前还没入队的d_i\leq kd?i??k的最大的ii。于是时间复杂度就是\text{O}((n+m) \log n)O((n+m)logn).

技术分享
///1085422276

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
#define pb push_back
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){
        if(ch==-)f=-1;ch=getchar();
    }
    while(ch>=0&&ch<=9){
        x=x*10+ch-0;ch=getchar();
    }return x*f;
}
//****************************************
const int  N=500000+50;
#define mod 1000000007
#define inf 10000007

int ind[N],head[N],t,n,m,K,vis[N];
vector<int > ans;
vector<int >G[N];
struct ss {
   int l,r,sum,index;
}tr[N*5];
struct sss {
  int to,next;
}e[N*2];
void init() {
  t=1;mem(head);mem(ind);ans.clear();mem(vis);
  for(int i=1;i<=n;i++)G[i].clear();
}
void add(int u,int v) {e[t].to=v;e[t].next=head[u];head[u]=t++;}
void build(int k,int s,int t) {
     tr[k].l=s;tr[k].r=t;
     if(s==t) {
        tr[k].sum=ind[s];
        tr[k].index=s;
        return ;
     }
     int  mid=(s+t)>>1;
     build(k<<1,s,mid);
     build(k<<1|1,mid+1,t);
     tr[k].sum=min(tr[k<<1].sum,tr[k<<1|1].sum);
}
int ask(int k,int s,int t,int c) {
    int ret;
    if(tr[k].l==tr[k].r&&tr[k].l==s) {
            return tr[k].index;
    }
    int mid=(tr[k].l+tr[k].r)>>1;
    if(tr[k<<1|1].sum<=c) {
        ret=ask(k<<1|1,mid+1,t,c);
    }
    else  {
        ret=ask(k<<1,s,mid,c);
    }
    return ret;
}
void update(int k,int x,int c) {
     if(tr[k].l==tr[k].r&&tr[k].l==x) {
        tr[k].sum+=c;
        return ;
     }
     int mid=(tr[k].l+tr[k].r)>>1;
     if(x<=mid) update(k<<1,x,c);
     else update(k<<1|1,x,c);
     tr[k].sum=min(tr[k<<1].sum,tr[k<<1|1].sum);
}
int main() {

    while(scanf("%d%d%d",&n,&m,&K)!=EOF) {
        init();int u,v,check;
        for( int i=1;i<=m;i++) {
            scanf("%d%d",&u,&v);
            ind[v]++;
            G[u].pb(v);
        }
        build(1,1,n);
        for(int i=n;i>=1;i--) {
            check=ask(1,1,n,K);
            ans.pb(check);
            K-=ind[check];
            update(1,check,inf);
            for(int j=0;j<G[check].size();j++) {
                update(1,G[check][j],-1);
                ind[G[check][j]]--;
            }
        }
        for(int i=0;i<ans.size()-1;i++) {
            printf("%d ",ans[i]);
        }
        printf("%d\n",ans[ans.size()-1]);
    }
  return 0;
}
代码

 

HDU5195 线段树+拓扑

标签:

原文地址:http://www.cnblogs.com/zxhl/p/4954311.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!