距离退役已经快一年了,以前和我的队友在赛场上飞扬跋扈的日子现在回忆起来还是很爽的。
今天是实验室2014年regional牡丹江赛区网络赛的日子,作为一名老队员我觉得参加这场比赛是一场义务。其实在去年我觉得我是可以不去的,因为有FG在,网络赛出线肯定是没有问题的。但是今年还是有点担心,不过因为我也好久不练了,虽然自己的水平肯定在学弟之下,但是感觉还是得刷一下存在感。
比赛刚开始看了最后一题J题。一开始感觉虽然数据比较小,但是还是可以用KMP优化,然后就自己写了一个KMP版额代码,结果WA了。下面是WA了的代码:
这个时候ZY说C题是图论,而我在图论方面比较擅长,所以我就看了。看懂题目后的初始的5分钟内我的思路从无向图双连通分量变化到了dfs加并查集,变化到了简单的dfs,记忆化搜索。然后就按照思路来,大致是
cnt[i]表示i能涉及到
ok[i]表示i当前能够访问
vis[i]表示i已经访问到,这是记忆化搜索所做的标记,上面两个都是标记。然后代码就很清晰了,但是交上去WA了,只能怪自己好久不练了。下面是错误的代码:
然后我看剩下的过的最多的是H题,但是想得太复杂了,最后还是没有想通。下面是错误的代码:
今天是实验室2014年regional牡丹江赛区网络赛的日子,作为一名老队员我觉得参加这场比赛是一场义务。其实在去年我觉得我是可以不去的,因为有FG在,网络赛出线肯定是没有问题的。但是今年还是有点担心,不过因为我也好久不练了,虽然自己的水平肯定在学弟之下,但是感觉还是得刷一下存在感。
比赛刚开始看了最后一题J题。一开始感觉虽然数据比较小,但是还是可以用KMP优化,然后就自己写了一个KMP版额代码,结果WA了。下面是WA了的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
char s[maxn];
int next[maxn] , len;
bool judge_ABABA(int nn) {
int lena = 2 * nn - len;
int lenb = nn - 2 * lena;
if(lena <= 0 || lenb <= 0) return false;
int p1 = lena , p2 = lena + lenb , p3 = nn , p4 = nn + lenb , p5 = len - 1;
for(int i=0;i<lena;i++) if(s[i] != s[p2+i] || s[i] != s[p4+i]) return false;
for(int i=0;i<lenb;i++) if(s[p1+i] != s[p3+i]) return false;
return true;
}
bool judge_ABABCAB(int nn) { // the same as AABA , some change
int lena = nn + 1;
int lenb = len - 3 * lena;
if(lena <= 0 || lenb <= 0) return false;
int p1 = lena , p2 = 2 * lena , p3 = len - lena , p4 = len;
for(int i=0;i<lena;i++) if(s[i] != s[p1+i] || s[i] != s[p3+i]) return false;
if(lena == 2 && s[0] == s[1]) return false;
if(lena != lenb) return true;
for(int i=0;i<lena;i++) if(s[i] != s[p2+i]) return true;
return false;
}
bool j_ABABA() {
for(int nn = next[len-1] + 1;nn!=-1;nn=next[nn]) {
if(judge_ABABA(nn)) return true;
}
return false;
}
bool j_ABABCAB() {
for(int nn = next[len-1];nn!=-1;nn=next[nn]) {
if(judge_ABABCAB(nn)) return true;
}
return false;
}
int main() {
int T;
scanf("%d" , &T);
while(T--) {
scanf("%s" , s);
len = strlen(s);
int j=0;
for(int i=0;i<len;i++) {
if(isalpha(s[i])) s[j++] = s[i];
}
len = j;
s[len] = 0;
//printf("%s\n" , s);
next[0] = -1;
j = -1;
for(int i=1;i<len;i++) {
while(j >= 0 && s[i] != s[j+1]) j = next[j];
if(s[i] != s[j+1]) next[i] = j;
else {
j ++;
next[i] = j;
}
}
//for(int i=0;i<len;i++) printf("%d " , next[i]);
bool ok = false;
if(j_ABABA()) ok = true;
else if(j_ABABCAB()) ok = true;
if(ok) puts("Yes");
else puts("No");
}
return 0;
}
当然作为一名老队员我觉得暴力肯定能过,但是暴力又不是我的风格,所以我就QQ了ZY让他找一个小学弟帮忙暴力过一下。事实证明后来暴力过了。
这个时候ZY说C题是图论,而我在图论方面比较擅长,所以我就看了。看懂题目后的初始的5分钟内我的思路从无向图双连通分量变化到了dfs加并查集,变化到了简单的dfs,记忆化搜索。然后就按照思路来,大致是
cnt[i]表示i能涉及到
ok[i]表示i当前能够访问
vis[i]表示i已经访问到,这是记忆化搜索所做的标记,上面两个都是标记。然后代码就很清晰了,但是交上去WA了,只能怪自己好久不练了。下面是错误的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 101000 , maxm = 404000;
int n , m , K , L;
struct Edge {
int v , next;
Edge () {}
Edge (int v,int next) : v(v) , next(next) {};
}edge[maxm];
int E , head[maxn];
void init() {
E = 0; memset(head,-1,sizeof(int)*(n+1));
}
void addedge(int u,int v) {
edge[E] = Edge(v,head[u]); head[u] = E++;
edge[E] = Edge(u,head[v]); head[v] = E++;
}
int st , rt;
//queue<int> q;
bool ok[maxn]; // can be solved
bool vis[maxn]; // has been solved
bool con[maxn]; // if a edge for i to st
int od[maxn];
void dfs(int u) {
con[u] = true;
if(!ok[u] || vis[u]) return;
vis[u] = true;
for(int i=head[u];i!=-1;i=edge[i].next) {
int v = edge[i].v;
con[v] = true;
if(!ok[v] || vis[v]) continue;
dfs(v);
}
return;
}
bool check() {
//puts("vis:");
//for(int i=1;i<=n;i++) if(vis[i]) printf("1");
//else printf("0");
//puts("");
//puts("ok:");
//for(int i=1;i<=n;i++) if(ok[i]) printf("1");
//else printf("0");
//puts("");
puts("con:");
for(int i=1;i<=n;i++) if(con[i]) printf("1");
else printf("0");
puts("");
}
int main() {
int T;
scanf("%d" , &T);
while(T--) {
scanf("%d%d%d" , &n,&m,&K);
init();
for(int i=1;i<=n;i++) {
vis[i] = false;
ok[i] = true;
con[i] = false;
}
for(int i=0;i<K;i++) {
scanf("%d" , &od[i]);
ok[od[i]] = false;
}
while(m--) {
int u , v;
scanf("%d%d" , &u,&v);
addedge(u , v);
}
scanf("%d" , &L);
for(int i=0;i<L;i++) {
scanf("%d" , &od[i]);
}
if(L < K) {
puts("No");
continue;
}
st = od[0];
con[st] = 1;
bool Ok = true;
//check();
for(int i=0;i<L;i++) {
int u = od[i];
ok[u] = true;
if(!con[u]) { Ok = false; break; }
dfs(u);
//check();
//*2*if(!vis[u]) { Ok = false; break; }
}
if(Ok) puts("Yes");
else puts("No");
}
return 0;
}
不过ZY还是没有辜负我的期望,找出了我代码中的错误,得到了正确的代码。下面是ZY正确的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 101000 , maxm = 404000;
int n , m , K , L, cnt;
struct Edge {
int v , next;
Edge () {}
Edge (int v,int next) : v(v) , next(next) {};
}edge[maxm] ;
int E , head[maxn] , flag[maxn] ;
void init() {
cnt = 0;
memset(flag, 0, sizeof(flag));
E = 0; memset(head,-1,sizeof(int)*(n+1));
}
void addedge(int u,int v) {
edge[E] = Edge(v,head[u] );
head[u] = E++;
edge[E] = Edge(u,head[v] );
head[v] = E++;
}
void ddfs(int x) {
if (flag[x] )
return;
flag[x] = 1;
cnt ++;
for(int i=head[x] ;i!=-1;i=edge[i] .next) {
int v = edge[i] .v;
ddfs(v);
}
}
int st , rt;
//queue<int> q;
bool ok[maxn] ; // can be solved
bool vis[maxn] ; // has been solved
bool con[maxn] ; // if a edge for i to st
int od[maxn] ;
void dfs(int u) {
con[u] = true;
if(!ok[u] || vis[u] )
return;
vis[u] = true;
for(int i=head[u] ;i!=-1;i=edge[i] .next) {
int v = edge[i] .v;
con[v] = true;
if(!ok[v] || vis[v] )
continue;
dfs(v);
}
return;
}
int main() {
int T;
scanf("%d" , &T);
while(T--) {
scanf("%d%d%d" , &n,&m,&K);
init();
for(int i=1;i<=n;i++) {
vis[i] = false;
ok[i] = true;
con[i] = false;
}
for(int i=0;i < K;i++) {
scanf("%d" , &od[i] );
ok[od[i] ] = false;
}
while(m--) {
int u , v;
scanf("%d%d" , &u,&v);
addedge(u , v);
}
scanf("%d" , &L);
for(int i=0;i<L;i++) {
scanf("%d" , &od[i] );
}
ddfs(1);
if(K != L || cnt != n){
puts("No");
continue;
}
st = od[0];
con[st] = 1;
bool Ok = true;
for(int i=0;i<L;i++) {
int u = od[i] ;
ok[u] = true;
if(!con[u] ) {
Ok = false;
break;
}
dfs(u);
}
if(Ok)
puts("Yes");
else
puts("No");
}
return 0;
}
然后我就想到毛爷爷的一句话:“世界是我们的,也是你们的,但是不管怎么样还是你们的”。ZY加油!
然后我看剩下的过的最多的是H题,但是想得太复杂了,最后还是没有想通。下面是错误的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 1010;
int T;
char s[maxn] , t[maxn] , s1[maxn] , s2[maxn] , s3[maxn];
void debug(int len1 , int len2) {
printf("len1 is %d\n" , len1);
printf("len2 is %d\n" , len2);
}
int main() {
scanf("%d" , &T);
while(T--) {
scanf("%s" , s);
strcpy(t , s);
int len = strlen(s);
bool ok = false;
if(len == 1) {
printf("%c\n" , s[0]-1);
continue;
}
else if(len == 2) {
if(s[0] <= s[1]) { printf("%c%c\n" , s[0],s[0]); continue; }
else if(s[0] > '1') { printf("%c%c\n" ,s[0]-1,s[0]-1); continue; }
else { puts("9"); continue; }
}
for(int i=1;i<len-1;i++) if(s[i] != '0') ok = true;
if(s[0] > '1' || s[len-1] > '1') ok = true;
if(ok == false) {
for(int i=1;i<len;i++) printf("9");
puts("");
continue;
}
int len1 = 0 , len2 = 0;
s1[len1++] = s[0];
s2[len2++] = s[0];
for(int i=1;i<len;i++) {
s1[len1++] = s[i];
if(len1+len2>=len) break;
if(s[i] != s[i-1]) s2[len2++] = s[i];
if(len1+len2>=len) break;
}
s1[len1] = s2[len2] = 0;
//strrev(s2);
for(int i=0;i<len2;i++) s3[i] = s2[len2-1-i]; s3[len2] = 0;
strcpy(s2 , s3);
//printf("%s%s\n" , s1 , s2);
strcat(s1 , s2);
if(strcmp(t , s1) > 0) {
puts(s1);
continue;
}
for(int ii=len-1;ii>=0;ii--) {
if(s1[ii] > '0') {
s1[ii] -= 1;
for(int jj=ii+1;jj<len;jj++) s1[jj] = '9';
strcpy(s , s1);
len1 = 0 , len2 = 0;
s1[len1++] = s[0];
s2[len2++] = s[0];
for(int i=1;i<len;i++) {
s1[len1++] = s[i];
if(len1+len2>=len) break;
if(s[i] != s[i-1]) s2[len2++] = s[i];
if(len1+len2>=len) break;
}
s1[len1] = s2[len2] = 0;
//strrev(s2);
for(int i=0;i<len2;i++) s3[i] = s2[len2-1-i]; s3[len2] = 0;
strcpy(s2 , s3);
//printf("%s%s\n" , s1 , s2);
strcat(s1 , s2);
if(strcmp(t , s1) > 0) {
puts(s1);
break;
}
}
}
//debug(len1,len2);
}
return 0;
}