QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#506267#9102. Zayin and ElementsPlentyOfPenaltyAC ✓90ms5728kbC++173.6kb2024-08-05 16:19:002024-08-05 16:19:00

Judging History

你现在查看的是最新测评结果

  • [2024-08-05 16:19:00]
  • 评测
  • 测评结果:AC
  • 用时:90ms
  • 内存:5728kb
  • [2024-08-05 16:19:00]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
std::mt19937 rd(std::chrono::steady_clock::now().time_since_epoch().count());

const int N = 505, p = 1000000007;
ll power(ll a,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1)res=res*a%p;
        a=a*a%p,n>>=1;
    }
    return res;
}
int A[N][N], B[N][N], t[N][N], id[N];
bool row[N] = {false}, col[N] = {false};
int n, m, girl[N]; // girl是匹配点,用来输出方案
// 高斯消元 O(n^3)
// 在传入B时表示计算逆矩阵,传入NULL则只需计算矩阵的秩
void Gauss(int A[][N], int B[][N], int n) {
  if (B) {
    memset(B, 0, sizeof(t));
    for (int i = 1; i <= n; i++) B[i][i] = 1;
  }
  for (int i = 1; i <= n; i++) {
    if (!A[i][i]) {
      for (int j = i + 1; j <= n; j++)
        if (A[j][i]) {
          swap(id[i], id[j]);
          for (int k = i; k <= n; k++) swap(A[i][k], A[j][k]);
          if (B)
            for (int k = 1; k <= n; k++) swap(B[i][k], B[j][k]);
          break;
        }
      if (!A[i][i]) continue;
    }
    int inv = power(A[i][i], p - 2);
    for (int j = 1; j <= n; j++)
      if (i != j && A[j][i]) {
        int t = (ll)A[j][i] * inv % p;
        for (int k = i; k <= n; k++)
          if (A[i][k]) A[j][k] = (A[j][k] - (ll)t * A[i][k]) % p;
        if (B)
          for (int k = 1; k <= n; k++)
            if (B[i][k]) B[j][k] = (B[j][k] - (ll)t * B[i][k]) % p;
      }
  }
  if (B)
    for (int i = 1; i <= n; i++) {
      int inv = power(A[i][i], p - 2);
      for (int j = 1; j <= n; j++)
        if (B[i][j]) B[i][j] = (ll)B[i][j] * inv % p;
    }
}
// 消去一行一列 O(n^2)
void eliminate(int r, int c) {
  row[r] = col[c] = true; // 已经被消掉
  int inv = power(B[r][c], p - 2);
  for (int i = 1; i <= n; i++)
    if (!row[i] && B[i][c]) {
      int t = (ll)B[i][c] * inv % p;
      for (int j = 1; j <= n; j++)
        if (!col[j] && B[r][j]) B[i][j] = (B[i][j] - (ll)t * B[r][j]) % p;
    }
}
void addedge(int x,int y)
{
    int w=rd()%p;
    A[x][y] = rd() % p;
    A[y][x] = -A[x][y]; // Tutte矩阵是反对称矩阵
}
void clear(){memset(A,0,sizeof A);}
int solve(int n)
{
    for(int i=1;i<=n;++i)id[i]=i;
        memcpy(t, A, sizeof(t));
        Gauss(A, NULL, n);
        int res=0;
        for (int i = 1; i <= n; i++)
            if (A[id[i]][id[i]]) ++res;
    return res/2;
}
int a[N],b[N],c[N];
vector<int>seq[N];
int main()
{
    cin.tie(0)->sync_with_stdio(0);
    int task;
    cin>>task;
    while(task--)
    {
        clear();
        int n,m;
        cin>>n>>m;
        int tot=n;
        for(int i=1;i<=m;++i)
        {
            cin>>a[i]>>b[i]>>c[i];
            int k;cin>>k;
            seq[i].resize(k);
            int pre=tot;
            for(int j=0;j<k;++j)
            {
                cin>>seq[i][j];
                for(int x=pre+1;x<=pre+a[i]+2*b[i]+c[i];++x)addedge(seq[i][j],x);
            }
            tot+=a[i]+2*b[i]+c[i];
        }
        int f=solve(tot);
        if(f!=n)
        {
            cout<<"-1\n";
            continue;
        }
        tot=n,clear();
        for(int i=1;i<=m;++i)
        {
            int pre=tot;
            tot+=a[i]+2*b[i]+2*c[i];
            for(int x=1;x<b[i]*2;++x)
                addedge(pre+a[i]+x,pre+a[i]+x+1);
            for(int x=1;x<=c[i];++x)
                addedge(pre+a[i]+2*b[i]+x,pre+a[i]+2*b[i]+x+c[i]);
            for(auto u:seq[i])
            {
                for(int j=pre+1;j<=pre+a[i]+2*b[i]+c[i];++j)addedge(u,j);
            }

        }
        int ff=solve(tot);
        cout<<(ff-n)<<endl;
    }
}

詳細信息

Test #1:

score: 100
Accepted
time: 1ms
memory: 5728kb

input:

2
5
2
2 3 1 2 3 1
1 1 1 3 4 5 2
5
2
2 3 1 1 3
1 0 1 2 1 2

output:

5
-1

result:

ok 2 lines

Test #2:

score: 0
Accepted
time: 90ms
memory: 5588kb

input:

5
9
10
0 0 10 2 3 8
0 0 10 2 4 6
0 8 2 2 2 4
0 0 10 3 1 3 8
0 4 6 2 2 3
0 8 2 3 2 6 7
0 9 1 2 1 7
0 2 8 3 1 4 9
0 7 3 1 5
0 0 10 3 5 6 9
3
10
0 9 1 1 2
0 5 5 1 1
0 1 9 1 1
0 7 3 1 1
0 7 3 0
0 0 10 0
0 6 4 1 3
0 9 1 0
0 7 3 0
0 9 1 1 2
90
20
0 6 4 12 1 4 5 22 32 64 66 67 73 87 88 89
0 1 9 12 3 8 21 3...

output:

94
97
155
151
152

result:

ok 5 lines