先找边双连通,拿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; }
就行。