想的时间比较长所以看题解了= =
原题:
Fj有N(N<=1000)头牛,每头牛都有独一无二的正整数 魅力值,Fj想让他们按
魅力值排序。
Fj已经知道M(1<=M<=10000)对奶牛的魅力值,但他发现,他还需要再做一张关
于另外C对奶牛的魅力值比较,才能推断出所有奶牛的魅力值的顺序。
现在请你帮他 算出最小的C值。
刚在拓扑排序方向上想,思路是每次选一个入度为0的点,让这个点向其它所有入度为0的点连边,然后这个点就是目前最高点了,然后就可以删掉不管了,所以可以直接删掉这个点
为了保证最坏情况所以每次删掉的点是所有入度为0的点中从这个点出发能到达的点最多的点
然后用堆搞一下,发现答案不对?
手玩小数据没问题,想了将近一下午无果,遵循经很多神犇"想的时间太长就不要再想"的建议,选择看题解
正解是用减法原理,确定完整的关系需要知道n*(n-1)/2条关系,已知的关系就是每个点能到达的点的个数的和,dfs搞一搞就可以了
然后遇到两个小问题,就是下面这两个dfs都是不对的:
/*void dfs(int x){注意这样可能会有重复的 f[x]=1; for(int i=LINK[x];i;i=e[i].next){ if(!f[e[i].y]) dfs(e[i].y); f[x]+=f[e[i].y]; } }*/ /*int dfs(int x){这样也可能会有重复的 int z=1; for(int i=LINK[x];i;i=e[i].next) z+=dfs(e[i].y); return z; }*/
反例很简单,请自己手玩
代码(我直接在原来堆的错误写法上改的,有一个堆还有各种乱搞,所以代码比较长= =):
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int read(){int z=0,mark=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mark=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mark; 11 } 12 struct ddd{int next,y;}e[11000]; int LINK[1100],ltop=0,rd[1100],cd[1100]; 13 inline void insert(int x,int y){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;cd[x]++;rd[y]++;} 14 int n,m; 15 //int QUEUE[1100000],head=0; 16 int ans=0; 17 bool flag[1100]; 18 int f[1100]; 19 int visited[1100]; 20 int max_heap[1100],size=0; 21 void push(int x){ 22 max_heap[size]=x; 23 int current=size,father=(size-1)>>1; 24 while(f[max_heap[current]]>f[max_heap[father]] && father>=0){ 25 swap(max_heap[current],max_heap[father]); 26 current=father,father=(current-1)>>1; 27 } 28 size++; 29 } 30 void updata(int x){ 31 int lchild=(x<<1)+1,rchild=(x<<1)+2; 32 int max_id=x; 33 if(lchild<size && f[max_heap[lchild]]>f[max_heap[max_id]]) max_id=lchild; 34 if(rchild<size && f[max_heap[rchild]]>f[max_heap[max_id]]) max_id=rchild; 35 if(max_id!=x){ 36 swap(max_heap[x],max_heap[max_id]); 37 updata(max_id); 38 } 39 } 40 void pop(){ 41 swap(max_heap[0],max_heap[size-1]); 42 size--; 43 updata(0); 44 } 45 /*void dfs(int x){注意这样可能会有重复的:(1,2),(3,2) 46 f[x]=1; 47 for(int i=LINK[x];i;i=e[i].next){ 48 if(!f[e[i].y]) dfs(e[i].y); 49 f[x]+=f[e[i].y]; 50 } 51 }*/ 52 /*int dfs(int x){这样也可能会有重复的,比如(1,2),(2,3),(1,3) 53 int z=1; 54 for(int i=LINK[x];i;i=e[i].next) z+=dfs(e[i].y); 55 return z; 56 }*/ 57 int dfs(int x,int y){ 58 int z=1; 59 for(int i=LINK[x];i;i=e[i].next)if(visited[e[i].y]!=y){ 60 visited[e[i].y]=y; 61 z+=dfs(e[i].y,y); 62 } 63 return z; 64 } 65 int main(){//freopen("ddd.in","r",stdin); 66 memset(flag,0,sizeof(flag)); 67 cin>>n>>m; 68 int _left,_right; 69 while(m --> 0){//趋向于 70 _left=read(),_right=read(); 71 insert(_left,_right); 72 } 73 //for(int i=1;i<=n;++i)if(!rd[i]) QUEUE[++head]=i,++cnt; 74 for(int i=1;i<=n;++i) ans+=dfs(i,i)-1; 75 //for(int i=1;i<=n;++i)if(!rd[i]) push(i); 76 /*for(int i=1;i<=n;++i){ 77 cout<<rd[max_heap[0]]<<endl; 78 pop(); 79 }*/ 80 /*while(size){ 81 //cout<<ans<<" "<<cnt<<endl; 82 ans+=size-1; 83 int max_id=max_heap[0]; pop(); 84 for(int i=LINK[max_id];i;i=e[i].next){ 85 rd[e[i].y]--; 86 if(!rd[e[i].y]) push(e[i].y); 87 } 88 //cout<<max_id<<endl; 89 }*/ 90 cout<<n*(n-1)/2-ans<<endl; 91 return 0; 92 }