cpp 对拍

众所周知,考试有两个,一个是暴力一个是正解。

排除有时候只有一个

暴力检验正解的正确性就是对拍。

这是暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<stack>

#define int long long

const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

using namespace std;

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){ x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}

int n, m, val[C], l, r, Ans, ind[C], cnt, all[C];
struct node
{
	int u, v;
} a[C];
struct edge
{
	int v, nxt;
} e[C], E[C];
int ecnt, head[C];
void add_edge(int u, int v)
{
	e[++ecnt] = (edge){ v, head[u]};
	head[u] = ecnt;
}
int Ecnt, Head[C];
void Add_edge(int u, int v)
{
	E[++Ecnt] = (edge){v, Head[u]};
	Head[u] = Ecnt;
}
queue<int> q;
int dfn[C], low[C], tot, id[C], cir_num;
bool vis[C];
stack<int> s;
void Tarjan(int x)
{
	dfn[x] = low[x] = ++tot;
	s.push(x), vis[x] = 1;
	for (int i = head[x]; i; i = e[i].nxt)
	{
		int v = e[i].v;
		if(!dfn[v])
		{
			Tarjan(v);
			low[x] = min(low[x], low[v]);
		}
		else if(vis[v]) low[x] = min(dfn[v], low[x]);
	}
	int k;
	if(low[x] == dfn[x])
	{
		do
		{
			k = s.top(), id[k] = x, vis[k] = 0;
			s.pop(), all[x]++;
			if(x == k) break;
			val[x] += val[k];
		}
		while(1);
	}
}
int tmp[C], Ind[C];
bool Check(int x)
{
	for (int i = 1; i <= n; i++) tmp[i] = val[i], Ind[i] = ind[i];
	for (int i = 1; i <= n; i++) if(!Ind[i] && id[i] == i){ q.push(i); }
	int cs = m;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for (int i = Head[u]; i; i = E[i].nxt)
		{
			int v = E[i].v;
			if(tmp[u] < x * all[u])
			{
				tmp[v] = tmp[v] - (x * all[u] - tmp[u]), tmp[u] = all[u] * x;
			}
			Ind[v]--;
			if(!Ind[v]) q.push(v);
		}
	}
	for (int i = 1; i <= n; i++)
	{
		if(id[i] == i)
		{
			if(tmp[i] < x * all[i]) cs = cs - (x * all[i] - tmp[i]);
		}
	}
	if(cs < 0) return false;
	return true;
}
signed main()
{
	freopen("a.in", "r", stdin);
	n = read(), m = read();
	for (int i = 1; i <= n; i++)
	{
		int x = read();
		if(x != -1)
		{
			add_edge(i, x);
			a[++cnt].u = i, a[cnt].v = x;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		val[i] = read();
		r = max(r, val[i]), l = min(l, val[i]);
	}
	for (int i = 1; i <= n; i++) if(!dfn[i]) Tarjan(i);
	for (int i = 1; i <= cnt; i++)
	{
		int x = a[i].u, y = a[i].v;
		if(id[x] != id[y]) Add_edge(id[x], id[y]), ind[y]++;
	}
	while(l <= r)
	{
		int mid = (l + r) >> 1;
		if(Check(mid)) Ans = mid, l = mid + 1;
		else r = mid - 1;
	}
	printf("%lld", Ans);
	return 0;
}
/*
5 10
3 1 4 3 3
1 5 2 5 7
*/

这是正解

#include<iostream>
#include<cstdio>
#include<vector>
#define int long long
using namespace std;
const int MAXN = 1e6 + 10;

struct edge { int from, to, nxt; }e[MAXN << 1], E[MAXN << 1];
int head[MAXN], num_edge = 1;
int Head[MAXN], Num_edge = 1;

int n, m;
int a[MAXN], ind[MAXN];
int dfn[MAXN], low[MAXN], num[MAXN], t = 0, cnt = 0;
int stc[MAXN], sc = 0;
int Siz[MAXN], Val[MAXN], f[MAXN];
bool vis[MAXN];
vector<int> tr;

void add_edge(int from, int to) { e[++num_edge] = (edge){from, to, head[from]}, head[from] = num_edge; }
void Add_edge(int from, int to) { E[++Num_edge] = (edge){from, to, Head[from]}, Head[from] = Num_edge; }

void tarjan(int u) {
    stc[++sc] = u, vis[u] = true;
    dfn[u] = low[u] = ++cnt;
    for(int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if(!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
        else if(vis[v]) low[u] = min(low[u], dfn[v]);
    }
    if(dfn[u] == low[u]) {
        int pre = stc[sc--]; vis[pre] = false;
        num[pre] = ++t, Siz[t] ++, Val[t] += a[pre];
        while(u != pre) {
            pre = stc[sc--], vis[pre] = false;
            num[pre] = t, Siz[t] ++, Val[t] += a[pre];
        }
    }
}
void dfs(int u, int lim) {
    f[u] = Val[u] - lim * Siz[u];
    for(int i = Head[u]; i; i = E[i].nxt) {
        int v = E[i].to;
        dfs(v, lim);
        if(f[v] < 0) {
            f[u] += f[v];
        }
    }
}

bool Check(int mid) {
    int M = tr.size();
    int sum = 0;
    for(int i = 0; i < M; ++i) {
        dfs(tr[i], mid);
        if(f[tr[i]] < 0) sum = sum - f[tr[i]];
    }
    return sum <= m;
}

signed main() {
    freopen("a.in", "r", stdin);
    scanf("%lld%lld", &n, &m);
    for(int i = 1, u; i <= n; ++i) {
        scanf("%lld", &u);
        if(u == -1) continue;
        add_edge(u, i);
    }
    for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i);
    for(int u = 1; u <= n; ++u) {
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(num[u] == num[v]) continue;
            Add_edge(num[u], num[v]);
            ind[num[v]]++;
        }
    }
    for(int i = 1; i <= t; ++i) {
        if(!ind[i]) {
            tr.push_back(i);
        }
    }
    int l = 0, r = 1000000000, ans = 0;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(Check(mid)) {
            ans = mid, l = mid + 1;
        } else {
            r = mid - 1;
        }
    }
    printf("%lld\n", ans);
    return 0;
}

/*
8 5
-1 1 2 3 4 8 6 7
1 2 3 4 5 6 7 8
*/

这是数据生成器:

/*
work by: Ariel_
Knowledge:
Time:
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>

using namespace std;

int read() {
  int x = 0, f = 1; char c = getchar();
  while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
  while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}
int n, m;
int main(){
  freopen("a.in", "w", stdout);  
  n = rand() % 10 + 1, m = rand() % 10 + 1;
  cout<<n<<" "<<m<<"\n";
  for (int i = 1; i <= n; i++) {
  	int x = rand() % n + 1;
  	while(x == i) {
  	  x = rand() % n + 1;	 
	}
	cout<<x<<" ";
  }
  puts("");
  for (int i = 1; i <= n; i++) {
  	cout<<rand() % 100 + 1<<" ";
  }
  return 0;
}

要注意他们的读入程序要相同

都是freopen("xxx.in", "r", stdin);

下面是对拍程序:

/*
work by: Ariel_
Knowledge:
Time:
*/
#include<windows.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>

using namespace std;

int read() {
  int x = 0, f = 1; char c = getchar();
  while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
  while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}
int T = 1e5;
int main(){
  while(T--) {
    system("rand.exe > rand.txt");
    system("baoli.exe < rand.txt > baoli.txt");
    system("std.exe < rand.txt > std.txt");
    if(system("fc baoli.txt std.txt")) break;
  }
  if(T == 0) cout<<"no error";
  else cout<<"error";
  return 0;
}
上一篇:golang使用defer panic recover 函数进行控制


下一篇:搜索插入位置