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 }

 

posted @ 2020-09-30 18:08  emhhbw==  阅读(131)  评论(0)    收藏  举报