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