【BZOJ1703】【usaco2007margold】ranking the cows 奶牛的魅力排名

想的时间比较长所以看题解了= =

原题:

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 }
View Code
原文地址:https://www.cnblogs.com/JSL2018/p/6391311.html