Submission #393975

#TimeUsernameProblemLanguageResultExecution timeMemory
39397579brue철인 이종 경기 (APIO18_duathlon)C++14
100 / 100
258 ms41196 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

inline ll c2(ll x) { return x*(x-1)/2; }
inline ll c3(ll x) { return x*(x-1)*(x-2)/6; }

int n, m;
vector<int> link[100002];
ll ans;

void input();
void makeBCC();
void vertexCount();
void lastDFS();

int main(){
    input();
    makeBCC();
    vertexCount();
    lastDFS();
    printf("%lld", ans);
}

void input(){
    scanf("%d %d", &n, &m);
    for(int i=1; i<=m; i++){
        int x, y;
        scanf("%d %d", &x, &y);
        link[x].push_back(y);
        link[y].push_back(x);
    }
}

ll seenCnt;

int dfsn[100002];
int dcnt;
stack<pair<int, int> > stk;
vector<vector<pair<int, int> > > BCC;

vector<int> bccIdx[100002];
vector<int> tlink[200002];
int k;

stack<int> thisComponent;
ll con[200002];
ll vCount[200002];
ll score[200002];

int dfs(int x, int prv = -1){
    int result = dfsn[x] = ++dcnt;
    seenCnt++;
    thisComponent.push(x);
    for(auto y: link[x]){
        if(prv == y) continue;
        if(dfsn[x] > dfsn[y]) stk.push(make_pair(x, y));
        if(dfsn[y] > 0) result = min(result, dfsn[y]);
        else{
            int tmp = dfs(y, x);
            result = min(result, tmp);
            if(tmp >= dfsn[x]){
                vector<pair<int, int> > currBCC;
                while(!stk.empty() && stk.top() != make_pair(x, y)){
                    currBCC.push_back(stk.top());
                    stk.pop();
                }
                currBCC.push_back(stk.top());
                stk.pop();
                BCC.push_back(currBCC);

                for(auto p: currBCC){
                    bccIdx[p.first].push_back((int)BCC.size());
                    bccIdx[p.second].push_back((int)BCC.size());
                }
            }
        }
    }
    return result;
}

void makeBCC(){
    for(int i=1; i<=n; i++){
        if(!dfsn[i]){
            seenCnt = 0;
            dfs(i);
            ans += c3(seenCnt) * 6;

            while(!thisComponent.empty()){
                con[thisComponent.top()] = seenCnt;
                thisComponent.pop();
            }
        }
    }

    k = (int)BCC.size(); /// 트리의 정점 개수: n+k

    for(int i=1; i<=n; i++){
        sort(bccIdx[i].begin(), bccIdx[i].end());
        bccIdx[i].erase(unique(bccIdx[i].begin(), bccIdx[i].end()), bccIdx[i].end());
        for(auto g: bccIdx[i]){
            tlink[i].push_back(g+n);
            tlink[g+n].push_back(i);
            con[g+n] = con[i];
        }
    }
}

bool visited[200002];

void dfs2(int x, int prv = -1){
    if(x<=n) vCount[x]++;
    visited[x] = 1;
    for(auto y: tlink[x]){
        if(y == prv) continue;
        dfs2(y, x);
        vCount[x] += vCount[y];

        if(x>n){
            score[x] += c2(vCount[y]);
        }
    }
    if(x>n) score[x] += c2(con[x] - vCount[x]);
}

void vertexCount(){
    for(int i=1; i<=n+k; i++){
        if(!visited[i]){
            dfs2(i);
        }
    }
}

void dfs3(int x, int prv = -1){
    visited[x] = 1;
    for(auto y: tlink[x]){
        if(y == prv) continue;
        dfs3(y, x);

        if(x<=n){
            assert(y>n);
            ans -= (score[y] - c2(con[x] - vCount[y])) * 2;
        }
    }
    if(x<=n && prv != -1){
        ans -= (score[prv] - c2(vCount[x])) * 2;
    }
}

void lastDFS(){
    fill(visited+1, visited+n+k+1, 0);
    for(int i=1; i<=n+k; i++){
        if(!visited[i]){
            dfs3(i);
        }
    }
}

Compilation message (stderr)

count_triplets.cpp: In function 'void input()':
count_triplets.cpp:28:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   28 |     scanf("%d %d", &n, &m);
      |     ~~~~~^~~~~~~~~~~~~~~~~
count_triplets.cpp:31:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   31 |         scanf("%d %d", &x, &y);
      |         ~~~~~^~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...