欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Warm up(tarjan缩点建树+树的直径)

程序员文章站 2022-04-01 17:43:43
...
/*
Warm up
HDU - 4612
https://vjudge.net/problem/HDU-4612
tarjan缩点建树+树的直径
注意!!! 有重边,有重边,有重边!!!
*/
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;
#define maxm 2000010
#define maxn 200010
struct Edge{
	int v,next;
	bool cnt;
  bool cong;
}edgeI[maxm];
int headI[maxn];
int dfn[maxn],low[maxn];
int belong[maxn];
int du[maxn];
int cntI,total,block;
int dep[maxn];
vector<int> mp[maxn];
stack<int> st;
void addI(int u,int v,bool cong){
	edgeI[cntI].v=v;
	edgeI[cntI].cnt=false;
  edgeI[cntI].cong=cong;
	edgeI[cntI].next=headI[u];
	headI[u]=cntI++;
}
void init(int n){
	memset(headI,-1,sizeof headI);
	memset(dfn,0,sizeof dfn);
	memset(low,0,sizeof low);
	while(!st.empty()) st.pop();
	memset(belong,0,sizeof belong);
	cntI=total=block=0;
  for(int i=0;i<=n;i++) mp[i].clear();
}
void tarjan(int u,int fa,bool cong){
	dfn[u]=low[u]=++total;
	st.push(u);
	for(int i=headI[u];~i;i=edgeI[i].next){
		int v=edgeI[i].v;
    if(v==fa&&(!cong)) continue;
		if(!dfn[v]){
			tarjan(v,u,edgeI[i].cong);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u]){
				edgeI[i].cnt=true;
				edgeI[i^1].cnt=true;
			}
		}else if(low[u]>dfn[v]){
			low[u]=dfn[v];
		}
	}
	if(low[u]==dfn[u]){
		block++;
			while(1){
					int t=st.top();
					st.pop();
					belong[t]=block;
					if(t==u) break;
			}
	}
}
void dfs(int u){
  for(int i=0;i<mp[u].size();i++){
    int v=mp[u][i];
    if(dep[v]!=-1) continue;
    dep[v]=dep[u]+1;
    dfs(v);
  }
}
void solve(int n){
  tarjan(1,0,false);
  for(int u=1;u<=n;u++){
    for(int i=headI[u];~i;i=edgeI[i].next){
      if(edgeI[i].cnt){
        mp[belong[edgeI[i].v]].push_back(belong[u]);
        //cout<<belong[edgeI[i].v]<<"  "<<belong[u]<<endl;
      }
    }
  }
  memset(dep,-1,sizeof dep);
  dep[1]=0;
  dfs(1);
  int k=1;
  for(int i=1;i<=block;i++){
    if(dep[i]>dep[k]) k=i;
  }
  memset(dep,-1,sizeof dep);
  dep[k]=0;
  dfs(k);
  int ans=0;
  for(int i=1;i<=block;i++){
    ans=max(ans,dep[i]);
  }
  printf("%d\n", block-1-ans);
}
struct Node{
  int u,v;
}node[maxm];
bool cmp(Node a,Node b){
  if(a.u!=b.u) return a.u<b.u;
  else return a.v<b.v;
}
int main(){
	int n,m;
	int u,v;
	while(~scanf("%d %d", &n, &m)&&(n+m)){
		init(n);
    for(int i = 0;i < m;i++){
        scanf("%d%d",&u,&v);
        if(u==v)continue;
        if(u>v)swap(u,v);
        node[i].u = u;
        node[i].v = v;
    }
    sort(node,node+m,cmp);
    for(int i = 0;i < m;i++){
        if(i == 0 || (node[i].u!=node[i-1].u || node[i].v != node[i-1].v)){
            if(i < m-1 && (node[i].u==node[i+1].u && node[i].v == node[i+1].v)){
                addI(node[i].u,node[i].v,true);
                addI(node[i].v,node[i].u,true);
            }
            else{
                addI(node[i].u,node[i].v,false);
                addI(node[i].v,node[i].u,false);
            }
        }
    }
    solve(n);
	}
	return 0;
}

相关标签: acm竞赛