3355: [Usaco2004 Jan]有序奶牛

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 37  Solved: 19
[Submit][Status][Discuss]

Description

    约翰的N(1≤N≤1500)头牛排成一行挤奶时,有确定的顺序.牛被编成连续的号码1..N,他拥有L条关于奶牛顺序的信息,所有的信息都写成“A在B的前面”这样的形式,而且他知道最后一条是多余的.他觉得,有些冗余信息可以由其他信息推出,可以对这些信息进行精减.请帮助约翰删除尽可能多的冗余信息,但要保证能推出原有的顺序.可以保证的是,答案唯一,且最初的信息没有矛盾,如A在B前面,B在A前面.

Input

 
    第1行:两个整数N和L.
    第2到L+1行:每行两个整数X和Y(1≤X,y≤N),表示X在Y前.无重复.

Output

 
    第1行:整数U.
    第2到U+I行:输出精减后的信息,每行2个数字,按第1列数字排序.

Sample Input

5 6
3 5
4 2
5 2
2 1
3 1
4 1

Sample Output

4
2 1
3 5
4 2
5 2

HINT

3在1前,4在1前可推.输出的每一行,不能被其他推出.

分析:对于一条边x->y,若去掉之后x不能到达y,那么它是必需的。我们首先需要求出拓扑序列,然后我们按照拓扑序列反向加边,这样的目的就是为了在已知顺序的情况下维护哪些边可以互相到达,然后用一个bieset去判断一下哪些边是必须的。感谢claris和付大神对我的帮助

 #include "iostream"
#include "cstdio"
#include "cstring"
#include "bitset"
#include "algorithm"
using namespace std;
const int maxn=+;
const int maxm=+;
int n,m,ed,ed2;
int ind[maxn]; //入度
int adj[maxm]; //栈顶边对应的顶点
int next1[maxm]; //上一条边的编号
int tail[maxm]; //栈顶边的编号
int vis[maxn]; //存储拓扑排序序列
bitset<maxn>f[maxn];
void add(int x,int y){
ind[y]++;
adj[++ed]=y;
next1[ed]=tail[x];
tail[x]=ed;
}
int adj2[maxm];
int next2[maxm];
int tail2[maxm];
void add2(int x,int y){
adj2[++ed2]=y;
next2[ed2]=tail2[x];
tail2[x]=ed2;
}
typedef pair<int,int> P;
P p[maxm];
int main()
{
//freopen("a.txt", "r", stdin);
//freopen("b.txt", "w", stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) f[i][i]=;
ed=;
while(m--){ //数组式邻接表建图
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
} //构造拓扑排序序列
int cnt=;
for(int i=;i<=n;i++)
if(!(ind[i]))
vis[++cnt]=i; int h=;
ed2=;
while(h<=cnt){
int a;
for(int i=tail[a=vis[h++]];i;add2(adj[i],a),i=next1[i])
if(!(--ind[adj[i]]))
vis[++cnt]=adj[i];
} int ans=;
for(int i=;i<=n;i++){
int a;
for(int j=tail2[a=vis[i]];j;f[a]|=f[adj2[j]],j=next2[j])
if(!f[a][adj2[j]])
p[++ans]=P(adj2[j],a);
}
sort(p+,p++ans);
printf("%d\n",ans);
for(int i=;i<=ans;i++)
printf("%d %d\n",p[i].first,p[i].second);
return ;
}

BZOJ3355的更多相关文章

  1. BZOJ3355 : [Usaco2004 Jan]有序奶牛

    对于一条边x->y,若去掉之后x不能到达y,那么它是必需的. 首先拓扑排序求出拓扑序,然后按照终点拓扑序为第一关键字,起点拓扑序为第二关键字从小到大加边. 对于每个点,维护一个bitset,表示 ...

随机推荐

  1. POJ 1509 Glass Beads【字符串最小表示法】

    题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...

  2. Unity3D游戏开发之C#编程中常见数据结构的比较

    一.前言 Unity3D是如今最火爆的游戏开发引擎,它可以让我们能轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型的互动内容.它支持2D/3D游戏开发,据不完全统计,目前国内80%的手机游戏都 ...

  3. 洛谷 P4318 完全平方数

    题目描述 小 X 自幼就很喜欢数.但奇怪的是,他十分讨厌完全平方数.他觉得这些数看起来很令人难受.由此,他也讨厌所有是完全平方数的正整数倍的数.然而这丝毫不影响他对其他数的热爱. 这天是小X的生日,小 ...

  4. CPU 内存 硬盘的区别

    第一点:CPU 是处理器,内存和硬盘是存储器,受CPU 的控制.  第二点:由于内存的速度很快,在电脑运行的过程中,CPU通常只与内存交换数据,但内存断电数据就会全部丢失,因此电脑使用硬盘作为主要的存 ...

  5. [HTML5] Show Different Variations of Images Depending on the Viewport Width using Art Direction

    For small viewports, we may want to show a variation of the desktop image. A very common use case of ...

  6. Python--学习过程

    基础篇 Python基础篇 Python的数据类型 作业总结

  7. VS2012,VS2010无法生成dll程序集的解决办法

    在我们做项目的时候总会遇到dll程序集无法生成导致各种问题. 通常我们的做法就是清理项目,然后重新生成,或者直接到bin目录下删除所有dll,然后重新生成. 有时候某几个dll就是不生成. 这时候就需 ...

  8. String、StringBilder和StringBuffer之间的区别

    1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String 2.String <(StringBuffer,StringBuild ...

  9. 获取Wifi密码,不知道是不是真的

    package com.example.wifipassword; import java.util.List; import android.app.Activity; import android ...

  10. 对FreeMarker技术的思考

    依照静态非静态来划分网页分为两种:静态网页和非静态网页,究其优缺点而言,静态网页在用户訪问的时候响应快,可是因为里面的数据是写死的.所以致命的缺陷就是数据不能动态显示.非静态页面(如jsp)数据能够动 ...