农夫约翰有N(1≤N≤1000)头奶牛,每一头奶牛都有一个确定的独一无二的正整数产奶率.约翰想要让这些奶牛按产奶率从高到低排序. 约翰已经比较了M(1≤M≤10000)对奶牛的产奶率,但他发现,他还需要再做一张关于另外C对奶牛的产奶率比较,才能推断出所有奶牛的产奶率排序.请帮他确定C的最小值.
标签:
从输入样例中可以发现,约翰已经知道的排名有奶牛2>奶牛1>奶牛5和奶牛2>奶牛3>奶牛4,奶牛2排名第一.但是他还需要知道奶牛1的名次是否高于奶牛3来确定排名第2的奶牛,假设奶牛1的名次高于奶牛3.接着,他需要知道奶牛4和奶牛5的名次,假设奶牛5的名次高于奶牛4.在此之后,他还需要知道奶牛5的名次是否高于奶牛3.所以,他至少仍需要知道3个关于奶牛的排名.
题解:
首先,看到每行为x大于y,可以想到我们可以把每行看为有向边x->y。然后在纸上画一画,我们发现,这道题其实要求的是有多少个点对(i,j) (1<=i,j<=n),满足i通过有向图中的边到不了j且j通过有向图的边也到不了i。之后就是直接用Warshall求传递闭包(其实跟floyd差不多,2333)。但是我们不能用三重循环求解,会超时。于是就想到用bitset优化即可。
代码很短。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 bitset<1010> a[1010]; 4 int read() 5 { 6 int s=0,fh=1;char ch=getchar(); 7 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)fh=-1;ch=getchar();} 8 while(ch>=‘0‘&&ch<=‘9‘){s=s*10+(ch-‘0‘);ch=getchar();} 9 return s*fh; 10 } 11 int main() 12 { 13 int n,m,x,y,k,i,j,ans; 14 n=read();m=read(); 15 //for(i=1;i<=n;i++)a[i].reset(); 16 for(i=1;i<=m;i++) 17 { 18 x=read();y=read(); 19 a[x][y]=1; 20 } 21 //for(i=1;i<=n;i++)a[i][i]=1; 22 for(i=1;i<=n;i++) 23 { 24 for(j=1;j<=n;j++) 25 { 26 if(a[j][i])a[j]|=a[i];//j既然能到i,那么也可以到i能到的所有点. 27 } 28 } 29 ans=0; 30 for(i=1;i<=n;i++) 31 { 32 for(j=i+1;j<=n;j++) 33 { 34 if(a[i][j]==0&&a[j][i]==0)ans++; 35 } 36 } 37 printf("%d",ans); 38 fclose(stdin); 39 fclose(stdout); 40 return 0; 41 }
Bzoj 1703: [Usaco2007 Mar]Ranking the Cows 奶牛排名 传递闭包,bitset
标签:
原文地址:http://www.cnblogs.com/Var123/p/5281580.html