poj3694

先找边双连通,拿stack记录?(不确定正确性)。然后缩点后的点连成一棵树。拿vector储存边。然后由于数据弱,lca直接

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
//#include <unordered_set>
#define mkp make_pair
#define err cout<<"here"<<endl
using namespace std;
const double EPS=1e-8;
typedef long long lon;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef map<ull,int>::iterator IT;
const lon SZ=100010,SSZ=500010,APB=18,mod=100000007,one=97;
const lon INF=0x7FFFFFFF;
int n,m,cnt,tot,bel[SZ],val[SZ],pre[SZ];
int dfn[SZ],low[SZ],arr[SZ],dep[SZ];
struct nd{
    int to,wt;
    nd(int a=0,int b=0):to(a),wt(b){}
};
vector<int> mp[SZ];
int nex[SSZ],head[SZ],to[SSZ],num;
stack<int> stk;
pii ed[SSZ];

void add(int u,int v)
{
    ++num;
    nex[num]=head[u];
    head[u]=num;
    to[num]=v;
}

int find(int x)
{
    return arr[x]==x?x:arr[x]=find(arr[x]);
}

void adj(int x,int y)
{
    int rtx=find(x),rty=find(y);
    if(rtx!=rty)
    {
        arr[rtx]=rty;
    }
}

void tar(int x,int p)
{
    //cout<<"x: "<<x<<" "<<p<<endl;
    dfn[x]=low[x]=++cnt;
    stk.push(x);
    for(int i=head[x];i!=-1;i=nex[i])
    {
        int t=to[i];
        if((i!=(p^1))||p==-1)
        {
            if(!dfn[t])tar(t,i),low[x]=min(low[x],low[t]);
            else low[x]=min(low[x],low[t]);
            if(dfn[x]<low[t])
            {
                ++tot;
                //cout<<x<<" "<<p<<" "<<t<<" "<<stk.size()<<endl;
                for(;;)
                {
                    int top=stk.top();
                    stk.pop();
                    bel[top]=tot;
                    if(top==t)break;
                }
            }
        }
    }
    if(p==-1)
    {
        ++tot;
        //cout<<x<<" "<<tot<<endl;
        for(;;)
        {
            int top=stk.top();
            stk.pop();
            bel[top]=tot;
            if(top==x)break;
        }
    }
}

void dfs(int x,int p,int d)
{
    dep[x]=d;
    pre[x]=p;
    for(int i=0;i<mp[x].size();++i)
    {
        int t=mp[x][i];
        if(t!=p)
        {
            dfs(t,x,d+1);
        }
    }
}

int lca(int x,int y)
{
    int res=0;
    if(dep[x]<dep[y])swap(x,y);
    for(;dep[x]>dep[y];)
    {
        //cout<<"x: "<<x<<" "<<y<<endl;
        res+=val[x];
        val[x]=0;
        x=pre[x];
    }
    
    if(x==y)
    {
        return res;
    }
    for(;x!=y;)
    {
        
        res+=val[x]+val[y];
        val[x]=val[y]=0;
        x=pre[x],y=pre[y];
        //cout<<res<<" "<<x<<" "<<y<<endl;
    }
    return res;
}

void init()
{
    num=-1;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;++i)
    {
        int a,b;
        cin>>a>>b;
        ed[i].first=a,ed[i].second=b;
        add(a,b),add(b,a);
    }
    tar(1,-1);
    
    for(int i=1;i<=tot;++i)arr[i]=i;
    for(int i=1;i<=m;++i)
    {
        int a=ed[i].first,b=ed[i].second;
        a=bel[a],b=bel[b];
        if(find(a)!=find(b))
        {
            //cout<<"a: "<<a<<" "<<pre[2]<<" "<<b<<endl;
            adj(a,b);
            mp[a].push_back(b);
            mp[b].push_back(a);
        }
    }
    for(int i=2;i<=tot;++i)val[i]=1;
    int res=tot-1;
    dfs(1,-1,1);
//    for(int i=1;i<=tot;++i)
//    {
//        cout<<"pre: "<<dep[i]<<endl;
//    }
    int qnum;
    cin>>qnum;
    //cout<<" "<<res<<endl;
//    for(int i=1;i<=n;++i)
//    {
//        cout<<"bel "<<dep[i]<<endl;
//    }
    for(int i=1;i<=qnum;++i)
    {
        int a,b;
        cin>>a>>b;
        a=bel[a],b=bel[b];
        //cout<<"a: "<<a<<" "<<b<<" "<<lca(a,b)<<endl;
        //err;
        if(a!=b)res-=lca(a,b);
        cout<<res<<endl;
    }
}

void work()
{
    
}

void release()
{
    for(int i=1;i<=n;++i)
    {
        dfn[i]=low[i]=bel[i]=0;
    }
    for(int i=1;i<=tot;++i)
    {
        mp[i].clear();
        dep[i]=pre[i]=val[i]=0;
    }
    for(;stk.size();stk.pop());
    cnt=tot=0;
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    int casenum;
    //cin>>casenum;
    //cout<<casenum<<endl;
    //for(int time=1;time<=casenum;++time)
    for(int time=1;cin>>n>>m,n;++time)
    {
        
        cout<<"Case "<<time<<": "<<endl;
        init();
        work();
        release();cout<<endl;
    }
    return 0;
}

就行。

猜你喜欢

转载自www.cnblogs.com/gaudar/p/10853504.html