QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#506267 | #9102. Zayin and Elements | PlentyOfPenalty | AC ✓ | 90ms | 5728kb | C++17 | 3.6kb | 2024-08-05 16:19:00 | 2024-08-05 16:19:00 |
Judging History
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