QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#763013#2515. Graph CardsSanguineChameleonAC ✓18380ms160752kbC++206.7kb2024-11-19 17:44:462024-11-19 17:44:47

Judging History

This is the latest submission verdict.

  • [2024-11-19 17:44:47]
  • Judged
  • Verdict: AC
  • Time: 18380ms
  • Memory: 160752kb
  • [2024-11-19 17:44:46]
  • Submitted

answer

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f first
#define s second
#define mp make_pair
#define eb emplace_back
#define pb push_back
typedef pair<int,int> pii;

const int base = 11;
const int mod = 1e9+3;
const int mod2 = 1e9+7;
const int BASE = 31, MOD=1e9+9, MOD2=1e9+13;

struct Mint{
    int x1=0,x2=0;
    const static int m1 = mod;
    const static int m2 = mod2;
    Mint(){}
    Mint(int y){
        x1=x2=y;
        modd();
    }
    Mint(int y1, int y2){
        x1=y1;
        x2=y2;
        modd();
    }
    void modd(){
        x1=((x1%m1)+m1)%m1;
        x2=((x2%m2)+m2)%m2;
    }
    Mint operator+(Mint other){
        return Mint((x1+other.x1)%m1, (x2+other.x2)%m2);
    }
    Mint operator*(Mint other){
        return Mint((x1*other.x1)%m1, (x2*other.x2)%m2);
    }
    inline int sub(int a,int b, int m){
        return ( ((a-b)%m)+m )%m;
    }
    Mint operator-(Mint other){
        return Mint(sub(x1, other.x1, m1), sub(x2, other.x2, m2) );
    }
    bool operator<(Mint other){
        if(x1==other.x1)return x2<other.x2;
        return x1<other.x1;
    }
};

struct Mint2{
    int x1=0,x2=0;
    const static int m1 = MOD;
    const static int m2 = MOD2;
    Mint2(){}
    Mint2(Mint o){
        x1=o.x1;
        x2=o.x2;
        modd();
    }
    Mint2(int y){
        x1=x2=y;
        modd();
    }
    Mint2(int y1, int y2){
        x1=y1;
        x2=y2;
        modd();
    }
    void modd(){
        x1=((x1%m1)+m1)%m1;
        x2=((x2%m2)+m2)%m2;
    }
    Mint2 operator+(Mint2 other){
        return Mint2((x1+other.x1)%m1, (x2+other.x2)%m2);
    }
    Mint2 operator*(Mint2 other){
        return Mint2((x1*other.x1)%m1, (x2*other.x2)%m2);
    }
    inline int sub(int a,int b, int m){
        return ( ((a-b)%m)+m )%m;
    }
    Mint2 operator-(Mint2 other){
        return Mint2(sub(x1, other.x1, m1), sub(x2, other.x2, m2) );
    }
    Mint2 operator^(Mint2 o){
        return Mint2(x1^o.x1,x2^o.x2);
    }
    bool operator<(Mint2 other){
        if(x1==other.x1)return x2<other.x2;
        return x1<other.x1;
    }
};

const int mxn=1e6+5;
Mint ppows[2*mxn];
Mint2 PPOWS[2*mxn];

void init(){
    ppows[0]=Mint(1);
    PPOWS[0]=Mint2(1);
    for(int i=1;i<2*mxn;i++){
        ppows[i] = (ppows[i-1] * Mint(base));
        PPOWS[i] = (PPOWS[i-1] * Mint2(BASE));
        // ppows[i] = (ppows[i-1]*base)%mod;
        // PPOWS[i] = (PPOWS[i-1]*BASE)%MOD;
    }
}

vector<int> adjl[mxn];
bool vis[mxn];
bool on_cyc[mxn];

bool cyc_found,stop;int cyc_st;
vector<int> cycle_nodes;
//find cycle
void dfs(int nd, int p=-1){
    vis[nd]=1;
    for(int x:adjl[nd]){
        if(x==p)continue;
        if(vis[x]){
            //cycle found
            cyc_found=1;
            cyc_st=x;
            cycle_nodes.pb(nd);
            stop=0;
            break;
        }
        dfs(x,nd);
        if(cyc_found){
            if(!stop){
                cycle_nodes.pb(nd);
                if(nd==cyc_st)stop=1;
            }
            break;
        }
    }
}

int sz[mxn];
bool cmp(pair<Mint,int> a,pair<Mint,int>b){
    return mp(mp(a.f.x1,a.f.x2),a.s) < mp(mp(b.f.x1,b.f.x2),b.s);
}
Mint dfs_hash(int nd, int p=-1){
    sz[nd]=2;//the () at front and end
    vector<pair<Mint, int> > ch;//child hashes...
    for(int x:adjl[nd]){
        if(on_cyc[x])continue;
        if(x==p)continue;

        Mint h=dfs_hash(x,nd);
        ch.eb(h,sz[x]);
        sz[nd]+=sz[x];
    }
    sort(ch.begin(), ch.end(), cmp);
    //'('=1
    //')'=2
    Mint ans=Mint(1)*ppows[1];//'(' at start
    int cur_letters = 1;
    for(auto hp:ch){
        ans = ans + (hp.f*ppows[cur_letters]);
        cur_letters += hp.s;
    }
    // ans+=2*ppows[cur_letters+1];//')' at the end
    // ans%=mod;
    ans = ans+(ppows[cur_letters+1]*Mint(2));

    return ans;
}

typedef pair<Mint2,Mint2> pmm;
int cyc_length;
pmm hashg(int n){//n = node count
    //find cycle
    for(int i=1;i<=n;i++){
        on_cyc[i]=false;
        vis[i]=false;
    }
    dfs(1);
    // cout<<"Cycle: ";
    for(int nd:cycle_nodes){
        on_cyc[nd]=1;
        // cout<<nd<<' ';
    }
    // cout<<'\n';
    cyc_length = cycle_nodes.size();

    vector<Mint2> hashes;
    for(int nd:cycle_nodes){
        //dfs hash the tree
        hashes.pb(Mint2(dfs_hash(nd)));
    }
    //hash all possible cyclic shifts, find minimum
    Mint2 ans[2];
    for(int id=0;id<2;id++){
        Mint2 cur_hash=0;
        for(int i=0;i<hashes.size();i++){
            // cur_hash += (PPOWS[hashes.size()-i]*hashes[i])%MOD;
            // cur_hash %= MOD;
            cur_hash = cur_hash+(PPOWS[hashes.size()-i]*hashes[i]);
        }
        ans[id]=Mint2(cur_hash);
        for(int i=1;i<hashes.size();i++){
            // cur_hash*=BASE;
            // cur_hash%=MOD;
            cur_hash = cur_hash * Mint2(BASE);

            //hashes[i-1], go from ^h.size() to ^1
            // cur_hash -= (hashes[i-1]*PPOWS[hashes.size()+1])%MOD;
            // cur_hash += (hashes[i-1]*PPOWS[1])%MOD;
            // cur_hash%=MOD;
            // if(cur_hash<0)cur_hash += MOD;
            cur_hash = cur_hash - hashes[i-1]*PPOWS[hashes.size()+1];
            cur_hash = cur_hash + hashes[i-1]*PPOWS[1];

            // ans[id] = min(ans[id], cur_hash);
            if(cur_hash < ans[id])ans[id]=cur_hash;
            //cout << cur_hash.x1 << " " << cur_hash.x2 << '\n';
            //ans[id] = ans[id] + cur_hash;
        }
        reverse(hashes.begin(), hashes.end());
        //cout << '\n';
    }

    //cout << '\n';

    cyc_found=0;
    cycle_nodes.clear();
    if(ans[1]<ans[0])swap(ans[0],ans[1]);
    return mp(ans[0], ans[1]);
}

void solve(){
    int n;
    cin>>n;
    set<pair<pair<pii,pii>,pii> > ss;
    for(int i=0;i<n;i++){
        int k;cin>>k;
        for(int j=0;j<k;j++){
            int a,b;
            cin>>a>>b;
            adjl[a].pb(b);
            adjl[b].pb(a);
        }
        pmm h=hashg(k);
        for(int j=1;j<=k;j++)adjl[j].clear();//reset graph btw graphs

        auto neww = mp(mp(h.f.x1,h.f.x2),mp(h.s.x1,h.s.x2));

        ss.insert(mp(neww,mp(cyc_length,k) ));

        // cout<<i<<'\n';
        // cout<<cyc_length<<'\n';
    }
    cout<<ss.size()<<'\n';
}

int32_t main() {
    ios_base::sync_with_stdio(false);cin.tie(0);
    init();

    int tc;
    cin>>tc;
    while(tc--){
        solve();
    }
}
/*
Sam1:
1
2
4 1 2 2 3 3 1 1 4
4 1 2 2 3 3 1 2 4
(1)

Sam2:
2
2
4 1 2 2 3 3 1 1 4
5 1 2 2 3 3 1 2 4 2 5
3
9 1 2 2 5 5 7 7 6 6 3 3 1 2 4 7 9 9 8
9 1 4 4 2 2 3 3 5 5 7 7 6 6 4 7 8 8 9
9 1 2 2 5 5 4 4 1 4 7 7 8 8 6 8 9 5 3
(2 2)



*/

详细

Test #1:

score: 100
Accepted
time: 15ms
memory: 69156kb

input:

1
2
4 1 2 2 3 3 1 1 4
4 1 2 2 3 3 1 2 4

output:

1

result:

ok single line: '1'

Test #2:

score: 0
Accepted
time: 17ms
memory: 68408kb

input:

2
2
4 1 2 2 3 3 1 1 4
5 1 2 2 3 3 1 2 4 2 5
3
9 1 2 2 5 5 7 7 6 6 3 3 1 2 4 7 9 9 8
9 1 4 4 2 2 3 3 5 5 7 7 6 6 4 7 8 8 9
9 1 2 2 5 5 4 4 1 4 7 7 8 8 6 8 9 5 3

output:

2
2

result:

ok 2 lines

Test #3:

score: 0
Accepted
time: 5716ms
memory: 90812kb

input:

30
332526
3 3 2 3 1 2 1
3 2 3 3 1 1 2
3 1 3 1 2 3 2
3 3 2 2 1 1 3
3 2 1 2 3 1 3
3 1 3 1 2 3 2
3 1 2 2 3 3 1
3 2 1 2 3 1 3
3 3 1 3 2 1 2
3 1 3 1 2 3 2
3 1 3 3 2 2 1
3 1 2 2 3 3 1
3 3 1 3 2 1 2
3 2 1 2 3 1 3
3 3 2 2 1 1 3
3 1 2 1 3 2 3
3 1 2 1 3 2 3
3 2 3 2 1 3 1
3 1 2 1 3 2 3
3 3 1 1 2 2 3
3 1 3 1 2 ...

output:

1
4
5
89
93
242
628
1575
3401
5703
7718
8888
9258
9355
9356
9203
9211
89
239
648
1739
4541
10352
19037
27089
31567
33030
33068
32480
31503

result:

ok 30 lines

Test #4:

score: 0
Accepted
time: 4692ms
memory: 74284kb

input:

30
333333
3 2 1 2 3 3 1
3 1 2 3 2 3 1
3 3 2 1 3 1 2
3 2 3 2 1 3 1
3 2 3 2 1 1 3
3 1 2 3 2 3 1
3 3 1 2 1 3 2
3 1 3 1 2 3 2
3 1 3 2 3 1 2
3 2 1 3 2 3 1
3 2 3 1 2 1 3
3 3 1 1 2 3 2
3 3 2 3 1 1 2
3 2 1 3 1 3 2
3 3 2 1 2 3 1
3 3 2 1 2 1 3
3 2 3 2 1 1 3
3 1 2 3 2 3 1
3 3 1 1 2 3 2
3 1 3 1 2 2 3
3 1 2 3 2 ...

output:

1
2
5
13
33
89
240
653
1771
4753
11868
24982
40524
51128
54690
54119
52143
49848
47551
45441
43471
41664
40000
38461
37037
35714
34482
33333
32258
31250

result:

ok 30 lines

Test #5:

score: 0
Accepted
time: 18380ms
memory: 160752kb

input:

30
2
500000 12446 494050 179161 216388 282442 232792 428247 130742 87062 493860 276791 469755 342468 58973 93535 429405 5662 112197 121541 62083 28611 427877 376918 349780 372239 58010 457751 308686 448844 473714 151350 480692 152372 415617 311966 298916 302690 200753 75481 396263 318635 79619 39930...

output:

1
2
2
1
1
2
2
1
1
2
2
1
1
2
2
1
1
2
2
1
1
2
2
1
1
2
2
1
1
2

result:

ok 30 lines

Test #6:

score: 0
Accepted
time: 210ms
memory: 108524kb

input:

1
4
240000 1 2 2 3 3 4 4 7 1 5 2 6 7 8 8 9 9 10 10 13 7 11 8 12 13 14 14 15 15 16 16 19 13 17 14 18 19 20 20 21 21 22 22 25 19 23 20 24 25 26 26 27 27 28 28 31 25 29 26 30 31 32 32 33 33 34 34 37 31 35 32 36 37 38 38 39 39 40 40 43 37 41 38 42 43 44 44 45 45 46 46 49 43 47 44 48 49 50 50 51 51 52 52...

output:

2

result:

ok single line: '2'