BZOJ1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名

n<=1000头牛各有一个未知值Ai,已知m<=10000条形如Ax>Ay的不等关系,求将整个序列排序的最少比较次数。

Aa>Ab,Ab>Ac -------> Aa>Ac,传递性,因此按m条不等关系连边建图,求出传递闭包,就是已知的关系。

求出传递闭包中的i≠j的0的个数即可。错误!连的图是有向图,而已知大于关系后其实另一边已知一个小于关系,所以用n*n,减去1的个数*2,再减(i,j),i=j的n个,再除以2得到答案。

n3不可接受,因此用bitset优化floyd。代码如下:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<bitset>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n,m;
10 #define maxn 1011
11 #define maxm 10011
12 struct Edge{int to,next;};
13 struct Graph
14 {
15     bitset<maxn> mp[maxn];
16     Graph() {memset(mp,0,sizeof(mp));}
17     void insert(int x,int y) {mp[x][y]=1;}
18     void floyd()
19     {
20         for (int j=1;j<=n;j++)
21             for (int i=1;i<=n;i++)
22                 if (mp[i][j]) mp[i]|=mp[j];
23     }
24     int getans()
25     {
26         int one=0;
27         for (int i=1;i<=n;i++)
28             for (int j=1;j<=n;j++)
29                 one+=mp[i][j];
30         return (n*(n-1)-one*2)/2;
31     }
32 }G;
33 int x,y;
34 int main()
35 {
36     scanf("%d%d",&n,&m);
37     for (int i=1;i<=m;i++)
38     {
39         scanf("%d%d",&x,&y);
40         G.insert(x,y);
41     }
42     G.floyd();
43     printf("%d\n",G.getans());
44     return 0;
45 }
View Code

其实这个题是个错题,但错题错做。比如输入5 0,答案是10,但可以比较8次就出来。就是在一个已知有序数列中二分插入一个数,只是人工处理的情况下不需要进行区间移动之类的。

posted @ 2017-07-28 10:55  Blue233333  阅读(261)  评论(0编辑  收藏  举报