首页 > 代码库 > [NOIp2013普及组]车站分级
[NOIp2013普及组]车站分级
思路:
对于每一趟车,将区间内所有经停的站和所有未经停的站连一条边,表示前者优先级一定高于后者,然后用Kahn跑一遍拓扑排序即可。然而这样会创造大量多余的边,会TLE1个点。
考虑一种优化:因为每趟车本身也有一个优先级,因此可以将这趟车也看作一个点,每次先所有将经停的站连一条边到这两车上,表示这些站的优先级一定大于等于车的优先级,再将车连若干边到未经停的点,表示车的优先级一定大于未经停的站的优先级。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^‘0‘; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘);10 return x;11 }12 const int N=2001,M=1000001;13 struct List {14 int to,next;15 };16 List e[M];17 int sz=0;18 int h[N]={0};19 int in[N]={0};20 inline void add_edge(const int u,const int v) {21 e[++sz]=(List){v,h[u]};22 h[u]=sz;23 in[v]++;24 }25 const int inf=0x7fffffff;26 int ans=0;27 int n,m;28 inline void kahn() {29 std::queue<std::pair<int,int> > q;30 for(register int i=1;i<=n;i++) {31 if(!in[i]) q.push(std::make_pair(i,1));32 }33 while(!q.empty()) {34 int x=q.front().first,d=q.front().second;35 q.pop();36 for(register int i=h[x];i;i=e[i].next) {37 if(!--in[e[i].to]) {38 q.push(std::make_pair(e[i].to,d+1));39 }40 }41 ans=std::max(ans,d);42 }43 }44 int main() {45 n=getint(),m=getint();46 int b[n+1];47 for(register int i=1;i<=m;i++) {48 memset(b,0,sizeof b);49 int s=getint();50 int S=getint();51 b[S]=true;52 for(register int j=2;j<s;j++) {53 b[getint()]=true;54 }55 int T=getint();56 b[T]=true;57 for(register int j=S;j<=T;j++) {58 if(b[j]) {59 add_edge(j,i+n);60 }61 else {62 add_edge(i+n,j);63 }64 }65 }66 kahn();67 printf("%d\n",(ans+1)>>1);68 return 0;69 }
[NOIp2013普及组]车站分级
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。