学了这么久的OI还不会对拍,下定决心准备学对拍,上网一搜,全是在Windows下对拍的*.bat*文件,然而Ubuntu表示水土不服,~~竟然有度娘搜不到的东西,~~最后还是找同机房cgz神犇要的对拍程序,衷心感谢
关于对拍
对拍可以找出自己找不出来的一些问题,有时候应该是大多时候样例太水了,比如输入1,输出2,对拍自己出数据自己测,还可以控制数据范围
如何对拍
对拍有四个程序,分别是
①自己的程序 -----正確性未知
②暴力程序 --------保证正确性却不保证速度
③数据生成器 -----生成输入数据
④对拍程序 --------用于重复执行对拍流程
假设 1. c p p 1.cpp 1.cpp为自己的程序, 2. c p p 2.cpp 2.cpp为标程或暴力, m a k e . c p p make.cpp make.cpp为数据生成器, d p . c p p dp.cpp dp.cpp为对拍程序
前两个程序中应分别使用如下文件输入输出:
1.cpp
freopen("in","r",stdin);
freopen("1.out","w",stdout);
2.cpp
freopen("in","r",stdin);
freopen("2.out","w",stdout);
数据生成器应使用srand语句以保证每次生成的数据不同,并保证数据生成的格式与题目要求一致:
srand(time(0));
或
srand(time(NULL));
或
srand(你的生日);
对拍程序:
#include<bits/stdc++.h>
using namespace std;
int main(){
int c=0;
do{
if(c)printf("#%d AC\n",c);
++c;
system("./make");
system("./1");
system("./2");
}while(!system("diff 1.out 2.out"));
printf("#%d WA\n",c);
return 0;
}
例
对拍模板以 [HAOI2006]受欢迎的牛为例题
1号为待测程序
2号为暴力程序||标程
make为数据生成器
dp为对拍程序
注意俩程序输出格式必须相同,不省略行末空格,文尾回车
感谢cgz神犇提供dp模板
十分美观的 待测程序
#include<bits/stdc++.h>
using namespace std;
#define cl(x) memset(x,0,sizeof(x))
template <typename _Tp> inline void read(_Tp &x){
char c11=getchar();x=0;bool booo=0;
while(c11<'0'||c11>'9'){if(c11=='-')booo=1;c11=getchar();}
while(c11>='0'&&c11<='9'){x=x*10+c11-'0';c11=getchar();}
if(booo)x=-x;
return ;
}
const int maxn=10050,maxm=50050;
struct node {int v,nxt;} a[maxm];
int head[maxn],p=0;
int low[maxn],dfn[maxn];
bool vis[maxn];
int num__=0;
int sta[maxn],top=0;
int colour=0;
int leaf[maxn];
int A[maxm],B[maxm];
int tot[maxn];
struct node1 {int v,nxt;} b[maxm];
int head1[maxn],pp=0;
int es[maxn];
int n,m;
inline void app(int x,int y);
inline void add(int u,int v);
void init();
void again();
void tarjan(int x){
low[x]=dfn[x]=++num__;
vis[x]=1;
sta[++top]=x;
for(int i=head[x];i;i=a[i].nxt){
int v=a[i].v;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(vis[v])low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x]){
vis[x]=0;
leaf[x]=++colour;
es[colour]++;
for(;sta[top]!=x;top--){
leaf[sta[top]]=colour;
vis[sta[top]]=0;
es[colour]++;
}
top--;
}
return ;
}
void work(){
int temp=0,tem;
for(int i=1;i<=colour;i++)
if(!tot[i]){
temp++;
tem=i;
}
if(temp!=1)putchar('0');
else printf("%d",es[tem]);
return ;
}
int main(){freopen("in","r",stdin);freopen("1.out","w",stdout);
init();
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
again();
work();
return 0;
}
void init(){
cl(head);cl(low);cl(dfn);cl(vis);cl(tot);cl(es);
read(n);read(m);
for(int i=1;i<=m;i++){
read(A[i]);read(B[i]);
add(A[i],B[i]);
}
return ;
}
inline void app(int x,int y){
if(leaf[x]==leaf[y])return ;
b[++pp].v=leaf[y];
b[pp].nxt=head1[leaf[x]];
head1[leaf[x]]=leaf[y];
tot[leaf[x]]++;
return ;
}
void again(){
for(int i=1;i<=m;i++){
app(A[i],B[i]);
}
return ;
}
inline void add(int u,int v){
a[++p].v=v;
a[p].nxt=head[u];
head[u]=p;
return ;
}
丑陋的 标程
#include<cstdio>
#include<algorithm>
#define N 10009
#define M 50009
using namespace std;
int en,en1,n;
struct edge{
int e;
edge *next;
}*v[N],*v1[N],ed[M],ed1[M];
void add_edge(int s,int e){
en++;
ed[en].next = v[s],v[s] = ed+en,v[s]->e = e;
}
void add_edge1(int s,int e){
en1++;
ed1[en1].next = v1[s],v1[s] = ed1+en1,v1[s]->e =e;
}
int t,cnt,low[N],dfn[N],belong[N],siz[N],out[N],sta[N],stop = 1;
bool instack[N];
void dfs(int now){
t++;
low[now] = dfn[now] = t;
instack[now] = true;
sta[++stop] = now;
for(edge *e = v[now];e;e=e->next)
if(!dfn[e->e]){
dfs(e->e);
low[now] = min(low[now],low[e->e]);
}
else if(instack[e->e])low[now] = min(low[now],dfn[e->e]);
if(dfn[now] == low[now]){
cnt++;
int si = 0;
while(sta[stop] != now){
int j = sta[stop];
belong[j] = cnt;
instack[j] = false;
stop--;
si++;
}
si++;
stop--;
instack[now] = false;
belong[now] = cnt;
siz[cnt] = si;
}
}
int tarjan(){
for(int a = 1; a <= n; a++)
if(!dfn[a])dfs(a);
for(int a = 1; a <= n; a++)
for(edge *e = v[a];e;e=e->next)
if(belong[a] != belong[e->e])
add_edge1(belong[a],belong[e->e]);
for(int a = 1; a <= cnt; a++)
for(edge *e =v1[a];e;e=e->next)
out[a]++;
int ans = 0,b_hao = 0;
for(int a = 1; a<= cnt; a++)
if(out[a] == 0){
if(b_hao != 0){
ans = 0;
break;
}
ans += siz[a];
b_hao = a;
}
return ans;
}
int read(){
int x = 0;
char ch =getchar();
while(ch < '0' || ch > '9')ch = getchar();
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
int main(){
freopen("in","r",stdin);
freopen("2.out","w",stdout);
int m;
n = read(),m = read();
for(int a = 1;a <= m; a++){
int u = read(),v = read();
add_edge(u,v);
}
int ans = tarjan();
printf("%d",ans);
return 0;
}
强悍的 数据生成器
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("in","w",stdout);
srand(time(0));
int n=rand()%10000;
while(n==1)n=rand()%10000;
int m=rand()%50000;
printf("%d %d\n",n,m);
for(int i=1;i<=m;i++){
int a=rand()%n+1;
int b=rand()%n+1;
while(a==b)b=rand()%n+1;
printf("%d %d\n",a,b);
}
return 0;
}
神奇的也是最最重要的 对拍程序
#include<bits/stdc++.h>
using namespace std;
int main(){
int cases=0;
do{
if(cases)
printf("#%d AC\n",cases);
cases++;
system("./make");
system("./1");
system("./2");
}while(!system("diff 1.out 2.out"));
printf("#%d WA",cases);
return 0;
}