HDU3686 Traffic Real Time Query System

找出所有的割点然后把两个割点之间的所有边缩成一个点

于是变成了求路径上割点数目


然而炸了3天=生命不息=Tle不止

和wzf2000对拍跑的还比他快QAQ


这是老的RE程序==QAQ两天半啊

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;++j)
#define red(j,k,l) for (int j=k;j>=l;--j)
#define min(a,b) (a)<(b)?(a):(b)
#define N 40009
#define M 400009

using namespace std;
int dfn[N],low[N],iscut[N],bbl[M],used[M],lnk[M][2],stk[M];
int st[N],to[M*2],ne[M*2],deep[N],bz[N][25],bl[N];
int n,m,cl,top,tme,cnt,Q;

int read(){
	
	char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	int k=ch-48;
	while (1){
		
		ch=getchar();
		if (ch<'0'||ch>'9') return k;
		k=k*10+ch-48;
		
	}
	
}

void add(int k,int l){
	
	to[++cnt]=l;
	ne[cnt]=st[k];
	st[k]=cnt;
	to[++cnt]=k;
	ne[cnt]=st[l];
	st[l]=cnt;
	
}

void tj(int k){
	
	dfn[k]=low[k]=++tme;
	for (int i=st[k];i;i=ne[i]){
		
		int ll=(i+1)/2;
		if (used[ll]) continue;
		stk[++top]=ll;
		used[ll]=1;
		if (k!=lnk[ll][0]) swap(lnk[ll][0],lnk[ll][1]);
		int l=to[i];
		if (dfn[l]==0){
			
			tj(to[i]);
			low[k]=min(low[k],low[l]);
			if (low[l]>=dfn[k]){
				
				int poi;
				cl++;
				iscut[k]++;
				do{
					
					bbl[stk[top]]=cl;
					poi=lnk[stk[top--]][0];
					
				}while (poi!=k);
				
			}
			
		}else low[k]=min(low[k],low[l]);
		
	}
	
}

void dfs(int k,int fa,int lych){
	
	deep[k]=deep[fa]+1;
	bz[k][0]=fa;
	bl[k]=lych;
	for (int i=st[k];i;i=ne[i])
		if (to[i]!=fa)
			dfs(to[i],k,lych);
	
}

void init(){
	
	rep(i,1,n) dfn[i]=low[i]=iscut[i]=st[i]=0;
	rep(i,1,m) bbl[i]=used[i]=0,lnk[i][0]=read(),lnk[i][1]=read();
	cnt=cl=tme=0;
	rep(i,1,m) if (lnk[i][0]!=lnk[i][1]) add(lnk[i][0],lnk[i][1]);
				   else cnt+=2;
	rep(i,1,n) if (dfn[i]==0) top=0,tj(i),iscut[i]--;
	
	/* check *//*
	rep(i,1,m) printf("%d ",bbl[i]);
		printf("\n");
	rep(i,1,n) printf("%d ",iscut[i]);
		printf("\n");
	*//* check */
	
	rep(i,1,n) if (iscut[i]) iscut[i]=++cl;
	rep(i,1,cl) st[i]=deep[i]=bl[i]=0;
	n=cl;cl=0;cnt=0;
	rep(i,1,m) if (lnk[i][0]!=lnk[i][1]){
		
		if (iscut[lnk[i][0]]) add(bbl[i],iscut[lnk[i][0]]);
		if (iscut[lnk[i][1]]) add(bbl[i],iscut[lnk[i][1]]);
		
	}
	rep(i,1,n) if (deep[i]==0){
		
		cl++;
		dfs(i,i,cl);
		
	}
	rep(i,1,23) rep(j,1,n)
		bz[j][i]=bz[bz[j][i-1]][i-1];
	
}

int lca(int k,int l){
	
	if (deep[k]<deep[l]) swap(k,l);
	red(i,23,0) if (deep[k]-(1<<i)>=deep[l]) k=bz[k][i];
	if (k==l) return k;
	red(i,23,0) if (bz[k][i]!=bz[l][i])
		k=bz[k][i],l=bz[l][i];
	return bz[k][0];
	
}

void solve(){
	
	Q=read();
	while (Q--){
		
		int k=read(),l=read();
		k=bbl[k];l=bbl[l];
		if (bl[k]!=bl[l]||!k||!l){
			
			printf("0\n");
			continue;
			
		}
		int p=lca(k,l);
		printf("%d\n",(deep[k]+deep[l]-deep[p]*2)/2);
		
	}
	
}

int main(){
	
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	while (scanf("%d%d",&n,&m)!=EOF&&n&&m){
		
		init();
		solve();
		
	}
	return 0;
	
}


这是重打的TLE程序QAQ=另一个两天半啊


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define red(j,k,l) for (int j=k;j>=l;j--)
#define MST(a,b) memset(a,b,sizeof(a))
#define N 40005
#define M 400005

using namespace std;
struct _233{
	
	int k,l,i;
	
} b[M];
int stk[M],deep[N],low[N],wlc[N][25],bl[M],pi[N],p[M];
int to[M*2],ne[M*2],dfn[N],ict[N],st[N],nm[M*2],fa[N];
int n,m,cnt,top,cl,tme;
bool used[M];

void add(int k,int l){
	
	to[++cnt]=l;
	ne[cnt]=st[k];
	st[k]=cnt;
	to[++cnt]=k;
	ne[cnt]=st[l];
	st[l]=cnt;
	
}

int read(){
	
	char ch=getchar();
	while (ch<'0'||ch>'9') ch=getchar();
	int l=ch-48;
	while (1){
		
		ch=getchar();
		if (ch<'0'||ch>'9') return l;
		l=l*10+ch-48;
		
	}
	
}

void tj(int k,int ff){
	
	//printf("%d\n",k);
	dfn[k]=low[k]=++tme;
	for (int i=st[k];i;i=ne[i]) if (to[i]!=ff&&used[nm[i]]==0){
		
		stk[++top]=nm[i];
		used[nm[i]]=1;
		if (b[nm[i]].k!=k)
			swap(b[nm[i]].k,b[nm[i]].l);
		if (dfn[to[i]]==0){
			
			tj(to[i],k);
			if (low[to[i]]>=dfn[k]){
				
				ict[k]++;
				cl++;
				int poi;
				do{
					
					poi=stk[top--];
					bl[poi]=cl;
					//printf("---%d\n",poi);
					
				}while (b[poi].k!=k);
				
			}
			
		}
		low[k]=min(low[k],low[to[i]]);
		
	}
	
}

void dfs(int k,int ff){
	
	deep[k]=deep[ff]+1;
	wlc[k][0]=ff;
	pi[k]=tme;
	fa[k]=ff;
	for (int i=st[k];i;i=ne[i]) if (to[i]!=ff) dfs(to[i],k);
	
}

bool cmp(const _233 &x,const _233 &y){
	
	if (x.k+x.l!=y.k+y.l) return x.k+x.l<y.k+y.l;
	return min(x.k,x.l)<min(y.k,y.l);
	
}

void init(){
	
	cnt=tme=cl=0;
	MST(st,0);
	MST(dfn,0);
	MST(used,0);
	MST(ict,0);
	rep(i,1,m) b[i].k=read(),b[i].l=read(),b[i].i=i;
	sort(b+1,b+m+1,cmp);
	rep(i,1,m) p[b[i].i]=i;
	rep(i,1,m) if (b[i].k!=b[i].l&&(i==1||(b[i].k+b[i].l!=b[i-1].k+b[i-1].l||(b[i].k!=b[i-1].k&&b[i].k!=b[i-1].l)))) add(b[i].k,b[i].l),nm[cnt]=nm[cnt-1]=i;
	rep(i,1,n) if (dfn[i]==0) top=0,tj(i,i),ict[i]--;
	rep(i,1,n) if (ict[i]) ict[i]=++cl;
	//rep(i,1,n) printf("%d ",ict[i]);printf("\n");
	//rep(i,1,m) printf("%d ",bl[i]);printf("\n");
	
	cnt=tme=0;
	MST(st,0);
	MST(deep,0);
	rep(i,1,m) if (b[i].k!=b[i].l&&(i==1||(b[i].k+b[i].l!=b[i-1].k+b[i-1].l||(b[i].k!=b[i-1].k&&b[i].k!=b[i-1].l)))){
		
		if (ict[b[i].k]) add(ict[b[i].k],bl[i]);
			//,printf("%d %d\n",ict[b[i].k],bl[i]);
		if (ict[b[i].l]) add(ict[b[i].l],bl[i]);
			//,printf("%d %d\n",ict[b[i].l],bl[i]);
		
	}else if (b[i].k!=b[i].l) p[b[i].i]=p[b[i-1].i];
	rep(i,1,cl) if (deep[i]==0) tme++,dfs(i,i);
	rep(j,1,23) rep(i,1,cl) wlc[i][j]=wlc[wlc[i][j-1]][j-1];
	
}

int lca(int k,int l){
	
	if (deep[k]<deep[l]) swap(k,l);
	red(i,23,0) if (deep[l]+(1<<i)<=deep[k]) k=wlc[k][i];
	if (k==l) return k;
	red(i,23,0) if (wlc[k][i]!=wlc[l][i])
		k=wlc[k][i],l=wlc[l][i];
	return fa[k];
	
}

void solve(){
	
	int T=read();
	while (T--){
		
		int k=bl[p[read()]],l=bl[p[read()]];
		if (pi[k]!=pi[l]){
			
			printf("0\n");
			continue;
			
		}
		int p=lca(k,l);
		printf("%d\n",(deep[k]+deep[l]-deep[p]*2)/2);
		
	}
	
}

int main(){
	
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	while (scanf("%d%d",&n,&m),n&&m){
		
		init();
		solve();
		
	}
	//system("pause");
	
}



若看出我哪里炸了请告诉我=我已经弃疗了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值