제출 #51114

#제출 시각아이디문제언어결과실행 시간메모리
51114yp155136Duathlon (APIO18_duathlon)C++14
100 / 100
481 ms124520 KiB
#include <bits/stdc++.h>
using namespace std;

const int N = 800006;

int e[N];
vector<int> G[N];

int dfn_clock[N];

int stamp=0;

bool vis[N];
int low[N];
stack<int> sta;

vector<int> bcc[N];
vector<int> vv[N];
int bcc_no = 0;

void dfs(int now,int par)
{
    //cout << "now = " << now << " , par = " << par <<endl;
    dfn_clock[now] = low[now] = (++stamp);
    vis[now] = true;
    for (int i:G[now])
    {
        int to = (e[i]^now);
        if (to == par) continue;
        if (!vis[to])
        {
            sta.push(i);
            dfs(to,now);
            low[now] = min(low[now],low[to]);
            if (low[to] >= dfn_clock[now])
            {
                bcc_no++;
                int p;
                do {
                    p = sta.top();
                    bcc[bcc_no].push_back(p);
                    sta.pop();
                } while (p != i);
            }
        }
        else if (dfn_clock[to] < dfn_clock[now])
        {
            sta.push(i);
            low[now] = min(low[now],dfn_clock[to]);
        }
    }
}

typedef long long LL;

LL ans=0;

int cnt[N];
int in_bcc[N];
int type[N];
int sz[N];
int n,m;

int vis2[N];
int vis_id = 880301;

int xx[N],yy[N];

vector<int> G2[N];

int subtree_sz[N];

int n_cid[N];

int parr[N];

void dfs2(int now,int par,int cid)
{
    vis[now] = true;
    subtree_sz[now] = sz[now];
    parr[now] = par;
    for (int i:G2[now])
    {
        if(i != par)
        {
            dfs2(i,now,cid);
            subtree_sz[now] += subtree_sz[i];
        }
    }
    if (now == par)
    {
        n_cid[cid] = subtree_sz[now];
    }
}

LL tott1[N],tott2[N];

void dfs4(int now,int par,int cid)
{
    vis[now] = true;
    if (type[now] == 1)
    {
        vector<int> szz;
        for (int i:G2[now])
        {
            if (parr[now] == i)
            {
                szz.push_back(n_cid[cid] - subtree_sz[now]);
            }
            else
            {
                szz.push_back(subtree_sz[i]);
            }
        }
        LL tot=0,tot2=0;
        //cout << "now = " << now << " : ";
        for (int i:szz)
        {
            tot += i;
            tot2 += i*1LL*i;
            //cout << i << " ";
        }
        //assert((int)szz.size() <= 2);
        //cout<<endl;
        tott1[now] = tot;
        tott2[now] = tot2;
    }
    for (int i:G2[now])
    {
        if (i != par)
        {
            dfs4(i,now,cid);
        }
    }
    //cout << "now = " << now << " , subtree_sz = " << subtree_sz[now] << endl;
}

void dfs3(int now,int par,int cid)
{
    //cout << "now = " << now << " , par = " << par << endl;
    vis[now] = true;
    if (type[now] == 2)
    {
        //cout << "now = " << now << endl;
        //cut vertex
        for (int i:G2[now])
        {
            ans += (sz[i]*1LL*(sz[i]-1));
            //cout << "ans = " << ans << endl;
        }
        //two different
        vector<int> szz;
        for (int i:G2[now])
        {
            if (parr[now] == i)
            {
                szz.push_back(n_cid[cid] - subtree_sz[now]);
            }
            else
            {
                szz.push_back(subtree_sz[i]);
            }
        }
        LL tot=0,tot2=0;
        for (int i:szz)
        {
            tot += i;
            tot2 += i*1LL*i;
        }
        ans += (tot*tot-tot2);
        for (int i:G2[now])
        {
            int del_sz = -1;
            assert(type[i] == 1);
            if (parr[now] == i)
            {
                del_sz = subtree_sz[now];
            }
            else
            {
                del_sz = (n_cid[cid] - subtree_sz[i]);
            }
            LL tottt1 = tott1[i] - del_sz;
            LL tottt2 = tott2[i] - del_sz*1LL*del_sz;
            //cout << "i = " << i << " , now = " << now << " , del_Sz = " << del_sz << " , tott1 = " << tott1[i] << " , tott2 = " <<tott2[i] << endl;
            ans += (tottt1*tottt1) - tottt2;
            ans += 2*(sz[i])*(tottt1);
            //cout << "i = " << i << " , now = "<< now << " , del_sz = " << del_sz << " , tmp = " << (tot1*tot1) - tot2 << endl;
        }
        //cout << "ans = " << ans << endl;
    }
    else if (type[now] == 1)
    {
        //cout << "now = " << now << " , sz = " << sz[now] << " , n = " << n_cid[cid] << endl;
        ans += (sz[now]*1LL*(sz[now]-1)*1LL*(sz[now]-2));
        ans += 2*(sz[now]*1LL*(sz[now]-1)*1LL*(n_cid[cid]-sz[now]));
        vector<int> szz;
        for (int i:G2[now])
        {
            if (parr[now] == i)
            {
                szz.push_back(n_cid[cid] - subtree_sz[now]);
            }
            else
            {
                szz.push_back(subtree_sz[i]);
            }
        }
        LL tot=0,tot2=0;
        for (int i:szz)
        {
            tot += i;
            tot2 += i*1LL*i;
        }
        ans += sz[now]*(tot*tot-tot2);
    }
    for (int i:G2[now])
    {
        if (i != par)
        {
            dfs3(i,now,cid);
        }
    }
}

int main ()
{
    scanf("%d %d",&n,&m);
    for (int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d %d",&x,&y);
        e[i] = (x^y);
        G[x].push_back(i);
        G[y].push_back(i);
        xx[i] = x;
        yy[i] = y;
    }
    for (int i=1;i<=n;++i)
    {
        if (!vis[i])
        {
            dfs(i,i);
        }
    }
    /*for (int i=1;bcc_no>=i;i++)
    {
        cout << "i = " << i << " : ";
        for (int j:bcc[i]) cout << j << ' ';
        cout << endl;
    }*/
    for (int i=1;i<=bcc_no;++i)
    {
        ++vis_id;
        vector<int> v;
        for (int j:bcc[i])
        {
            if (vis2[ xx[j] ] != vis_id)
            {
                v.push_back(xx[j]);
                vis2[ xx[j] ] = vis_id;
            }
            if (vis2[ yy[j] ] != vis_id)
            {
                v.push_back(yy[j]);
                vis2[ yy[j] ] = vis_id;
            }
        }
        for (int j:v)
        {
            cnt[j]++;
        }
        vv[i] = v;
    }
    int vid = n;
    for (int i=1;i<=bcc_no;++i)
    {
        ++vid;
        type[vid] = 1;
        for (int j:vv[i])
        {
            if (cnt[j] == 1)
            {
                sz[vid]++;
            }
            else
            {
                G2[vid].push_back(j);
                G2[j].push_back(vid);
                type[j] = 2;
                sz[j] = 1;
            }
        }
    }
    int cid=0;
    memset(vis,0,sizeof(vis));
    for (int i=n+1;i <= vid;++i)
    {
        if (!vis[i])
        {
            dfs2(i,i,++cid);
        }
    }
    memset(vis,0,sizeof(vis));
    cid=0;
    for (int i=n+1;i<=vid;++i)
    {
        if (!vis[i])
        {
            dfs4(i,i,++cid);
        }
    }
    memset(vis,0,sizeof(vis));
    cid=0;
    for (int i=n+1;i<=vid;++i)
    {
        if (!vis[i])
        {
            dfs3(i,i,++cid);
        }
    }
    printf("%lld\n",ans);
}

컴파일 시 표준 에러 (stderr) 메시지

count_triplets.cpp: In function 'int main()':
count_triplets.cpp:228: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:232:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         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...