답안 #108633

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
108633 2019-04-30T12:36:18 Z oolimry 철인 이종 경기 (APIO18_duathlon) C++14
0 / 100
309 ms 28960 KB
#include <bits/stdc++.h>

using namespace std;
int n, m;
typedef vector<int> vi;
typedef pair<int,int> ii;
struct node{
    int depth = -1;
    int low;
    int parent;
    bool vis = false;
    bool isArti = false;
    vi adj;
};



static node g[200005];
int rootChildren = 0;
void dfs(int u){
    if(g[u].depth == -1) g[u].depth = g[g[u].parent].depth + 1;
    g[u].low = g[u].depth;
    g[u].vis = true;
    for(int i = 0;i < g[u].adj.size();i++){
        int v = g[u].adj[i];
        if(!g[v].vis){
            g[v].parent = u;
            if(g[u].depth == 0) rootChildren++;
            dfs(v);
            if(g[v].low >= g[u].depth){
                g[u].isArti = true;
            }
            ///if(g[v].low > g[u].depth{
                  ///u,v is a bridge
            ///}
            g[u].low = min(g[u].low,g[v].low);
        }
        else if(v != g[u].parent){
            g[u].low = min(g[u].low,g[v].low);
        }
    }
}


class UFDS {
typedef vector<int> vi;
public:
    vi p, rak, setSize;
    int numSets;

    void create(int n){
        setSize.assign(n, 1);
        numSets = n;
        rak.assign(n, 0);
        p.assign(n, 0);
        for(int i =0;i < n;i++){
            p[i] = i;
        }
    }

    int findSet(int i){
        return (p[i] == i) ? i : (p[i] = findSet(p[i]));
    }

    bool isSameSet(int i, int j){
        return findSet(i) == findSet(j);
    }

    void unionSet(int i, int j){
        if(isSameSet(i,j))
            return;
        numSets--;
        int x = findSet(i);
        int y = findSet(j);

        if(rak[x] > rak[y]) {
            p[y] = x; setSize[x] += setSize[y];
        }

        else {
            p[x] = y; setSize[y] += setSize[x];
            if(rak[x] == rak[y]) rak[y]++;
        }

    }
};


struct node2{
    long long s;
    long long dp = 0;
    bool isArti = false;
    bool vis = false;
    int r;
    vi adj;
};
vector<node2> bct; ///block-cut tree

long long root;
void dp(int u){
    if(bct[u].vis) return;
    bct[u].vis = true;
    bct[u].dp = bct[u].s;
    for(int i = 0;i < bct[u].adj.size();i++){
        int v = bct[u].adj[i];
        if(bct[v].vis) continue;
        dp(v);
        bct[u].dp += bct[v].dp;
    }
}
int main()
{
    //freopen("i.txt","r",stdin);
    scanf("%d %d",&n,&m);
    ii edges[m];
    for(int i = 0;i < m;i++){
        int a, b;
        scanf("%d %d",&a,&b);
        a--;
        b--;
        g[a].adj.push_back(b);
        g[b].adj.push_back(a);
        edges[i] = ii(a,b);
    }

    for(int i = 0;i < n;i++){
        if(!g[i].vis){
            rootChildren = 0;
            g[i].depth = 0;
            dfs(i);
            if(rootChildren > 1) g[i].isArti = true;
            else g[i].isArti = false; ///this line is needed
        }
    }
    UFDS uf;
    uf.create(n);
    unordered_map<int,int> artis;
    for(int i = 0;i < n;i++){
        if(g[i].isArti){
            node2 nn;
            nn.s = 1;
            nn.isArti = true;
            artis[i] = bct.size();
            bct.push_back(nn);
        }
    }

    for(int i = 0;i < m;i++){
        int a = edges[i].first;
        int b = edges[i].second;
        if(!g[a].isArti || !g[b].isArti){
            uf.unionSet(a,b);
        }
    }

    for(int i = 0;i < n;i++) g[i].vis = false;

    queue<int> bfs;
    for(int i = 0;i < n;i++){
        if(g[i].vis || g[i].isArti) continue;
        node2 nn;
        nn.s = 0;
        nn.isArti = false;
        int x = bct.size();
        bfs.push(i);
        unordered_set<int> pushedStuff;
        while(!bfs.empty()){
            int u = bfs.front();
            bfs.pop();
            if(g[u].isArti){
                int y = artis[u];
                pushedStuff.insert(y);
                continue;
            }
            if(g[u].vis) continue;
            g[u].vis = true;
            nn.s++;
            for(int j = 0;j < g[u].adj.size();j++){
                int v = g[u].adj[j];
                bfs.push(v);
            }
        }
        for(int y : pushedStuff){
            nn.adj.push_back(y);
            bct[y].adj.push_back(x);
        }
        bct.push_back(nn);
    }
    for(int i = 0;i < m;i++){
        int a = edges[i].first;
        int b = edges[i].second;
        if(g[a].isArti && g[b].isArti && !uf.isSameSet(a,b)){
            int x = artis[a];
            int y = artis[b];
            bct[x].adj.push_back(y);
            bct[y].adj.push_back(x);
        }
    }
    for(int i = 0;i < bct.size();i++){
        root = i;
        dp(i);
    }
    /*
    for(int i = 0;i < bct.size();i++){
        cout << bct[i].s << ", " << bct[i].dp << "| ";
        for(int j = 0;j < bct[i].adj.size();j++){
            cout << bct[i].adj[j] << " ";
        }
        cout << "\n";
    }
    */

    long long ans = 0ll;
    for(int i = 0;i < bct.size();i++){
        vector<long long> branches;
        long long total = 0ll;
        for(int j = 0;j < bct[i].adj.size();j++){
            if(bct[bct[i].adj[j]].dp <= bct[i].dp){
                branches.push_back(bct[bct[i].adj[j]].dp);
            }
        }
        branches.push_back(bct[bct[i].r].dp - bct[i].dp);
        for(int j = 0;j < branches.size();j++) total += branches[j];


        for(int j = 0;j < branches.size();j++){
            //cout << total << " " << branches[j] << " " << bct[i].s << "\n";
            ///branch1->self->branch2
            ans += branches[j] * bct[i].s * (total - branches[j]);

            ///self->self->branch or branch->self->self
            ans += 2ll * (bct[i].s) * (bct[i].s - 1ll) * branches[j];
        }

        if(!bct[i].isArti){
            long long neighbours = bct[i].adj.size();
            ans += (bct[i].s) * (bct[i].s - 1ll) * neighbours;
        }
    }

    cout << ans;







}

Compilation message

count_triplets.cpp: In function 'void dfs(int)':
count_triplets.cpp:24:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0;i < g[u].adj.size();i++){
                   ~~^~~~~~~~~~~~~~~~~
count_triplets.cpp: In function 'void dp(int)':
count_triplets.cpp:104:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0;i < bct[u].adj.size();i++){
                   ~~^~~~~~~~~~~~~~~~~~~
count_triplets.cpp: In function 'int main()':
count_triplets.cpp:178:29: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
             for(int j = 0;j < g[u].adj.size();j++){
                           ~~^~~~~~~~~~~~~~~~~
count_triplets.cpp:199:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0;i < bct.size();i++){
                   ~~^~~~~~~~~~~~
count_triplets.cpp:214:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0;i < bct.size();i++){
                   ~~^~~~~~~~~~~~
count_triplets.cpp:217:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j = 0;j < bct[i].adj.size();j++){
                       ~~^~~~~~~~~~~~~~~~~~~
count_triplets.cpp:223:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j = 0;j < branches.size();j++) total += branches[j];
                       ~~^~~~~~~~~~~~~~~~~
count_triplets.cpp:226:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         for(int j = 0;j < branches.size();j++){
                       ~~^~~~~~~~~~~~~~~~~
count_triplets.cpp:114:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d",&n,&m);
     ~~~~~^~~~~~~~~~~~~~~
count_triplets.cpp:118:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d %d",&a,&b);
         ~~~~~^~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 10 ms 8192 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 10 ms 8192 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 158 ms 19092 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 8320 KB Output is correct
2 Correct 12 ms 8292 KB Output is correct
3 Correct 15 ms 8256 KB Output is correct
4 Correct 11 ms 8320 KB Output is correct
5 Correct 11 ms 8320 KB Output is correct
6 Correct 11 ms 8320 KB Output is correct
7 Correct 10 ms 8320 KB Output is correct
8 Correct 10 ms 8448 KB Output is correct
9 Correct 10 ms 8320 KB Output is correct
10 Incorrect 10 ms 8320 KB Output isn't correct
11 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 282 ms 24516 KB Output is correct
2 Correct 269 ms 24732 KB Output is correct
3 Correct 257 ms 24700 KB Output is correct
4 Correct 274 ms 24748 KB Output is correct
5 Correct 264 ms 24604 KB Output is correct
6 Correct 309 ms 28960 KB Output is correct
7 Correct 267 ms 27164 KB Output is correct
8 Correct 260 ms 26652 KB Output is correct
9 Correct 252 ms 26332 KB Output is correct
10 Incorrect 262 ms 24604 KB Output isn't correct
11 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 9 ms 8320 KB Output is correct
2 Correct 10 ms 8328 KB Output is correct
3 Incorrect 9 ms 8320 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 231 ms 24388 KB Output is correct
2 Correct 285 ms 25244 KB Output is correct
3 Incorrect 259 ms 24604 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 10 ms 8192 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 10 ms 8192 KB Output isn't correct
2 Halted 0 ms 0 KB -