2019山东省赛重现总结
Median------神奇的Floyd大法
题目链接:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370519
题目大意:
给出 t 组测试样例,对于每组测试样例:第一行为元素个数 n 和元素间关系组数 m , 接下来的 m 行每行为两元素 ai bi ,且ai > bi ,问能不能将某个元素排序(由小到大,相邻不等)为中间元素, 中间元素定义为位于(n+1)/ 2处的元素,如果该元素符合这输出 1,否者输出 0,让按照原顺序输出各元素的可能结果。
思路:
首先想到的便是,当给的元素里面有相同的时候,肯定无法组成,这时全输出0就行。一个元素能不能成为中间元素,那么大于它的元素数肯定小于(n+1) / 2,小于它的元素数肯定小于(n+1) / 2,这时便要存储某个元素有多少个大于它的和小于它的,知道a > b,b > c,便可得到a > c,由于n < 100,通过Floyd去把元素链接起来,后面再通过链接后的sign数组记录各个元素的情况,最后按情况输出就行了。
解题代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 #include <string> 6 #include <cstring> 7 #include <map> 8 #include <set> 9 using namespace std; 10 const long long N = 1e10 + 7; 11 const int maxn = 2e5 + 5; 12 const long long INF = 8e18; 13 typedef long long ll; 14 #define for0(i,n) for(int i = 0;i < n;i++) 15 #define for1(i,n) for(int i = 1;i <= n;i++) 16 int sign[110][110],big[110],unbig[110]; 17 18 int main() 19 { 20 int t; 21 cin >> t; 22 while(t--){ 23 int n, m; 24 memset(sign,0,sizeof(sign)); 25 cin >> n >> m; 26 for(int i = 0;i < m;i++){ 27 int x,y; 28 scanf("%d%d",&x,&y); 29 sign[x][y] = 1; 30 } 31 for(int k = 1;k <= n;k++){ 32 for(int i = 1;i <= n;i++){ 33 for(int j = 1;j <= n;j++){ 34 if(sign[i][k] && sign[k][j]) 35 sign[i][j] = 1; 36 } 37 } 38 } 39 int i,j,temp = 0; 40 memset(big,0,sizeof(big)); 41 memset(unbig,0,sizeof(unbig)); 42 for(i = 1;i <= n;i++){ 43 for(j = 1;j <= n;j++){ 44 if(sign[i][j]){ 45 if(i == j){ 46 temp = 1; 47 break; 48 } 49 big[i]++; 50 unbig[j]++; 51 52 } 53 } 54 if(temp) 55 break; 56 } 57 if(temp){ 58 for(i = 0;i < n-1;i++) 59 cout << 0; 60 cout << 0 << endl; 61 62 63 } 64 else{ 65 for(i = 1;i <= n;i++){ 66 if(big[i] >= (n+1)/2 || unbig[i] >= (n+1)/2) 67 cout << 0; 68 else 69 cout << 1; 70 71 } 72 cout << endl; 73 } 74 75 76 } 77 return 0; 78 }
Game on a Graph
题目链接:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827370511
思路:
这个就是有 k 个人里面有一队的人和二队的人,后面给出 n 个点和 m 条连接情况,现在让这 k 个人依次去边(循环进行,写代码到后面这点忘了),直到某人去掉一边时,这些点不能相连时,该队伍失败,(这里我们老憨憨了,这个循环进行去边,我们写代码写着写着就忘取模了,后面wa了之后,我就以为是里面可能有重复情况,一直在整 去重复数据,我就带偏了他们,我是菜鸡),这个很显然找n个点相同需要的最少边,多出的那些边便是可去的边数,再取余人数就得到了位置。
解题代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 #include <string> 6 #include <cstring> 7 #include <map> 8 #include <set> 9 using namespace std; 10 const long long N = 1e10 + 7; 11 const int maxn = 2e5 + 5; 12 const long long INF = 8e18; 13 typedef long long ll; 14 #define for0(i,n) for(int i = 0;i < n;i++) 15 #define for1(i,n) for(int i = 1;i <= n;i++) 16 int main() 17 { 18 int t; 19 cin >> t; 20 while(t--){ 21 int l; 22 map<int,string>ma; 23 string ss; 24 cin >> l; 25 cin >> ss; 26 int n,m,x,y; 27 cin >> n >> m; 28 for(int i=0;i<m;i++){ 29 cin>>x>>y; 30 } 31 if(ss[(m - (n-1))%l] == '1') 32 cout << 2 << endl; 33 else 34 cout << 1 << endl; 35 } 36 return 0; 37 }