天天看點

【實用】關于Ubuntu下的對拍程式

學了這麼久的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;
}