BZOJ2088 [Poi2010]Teleportation

我们可以把所有点按距离源点的距离分层,每个层的点就可以和他上一层,同层和下一层的所有点连边

那么最后一定是1单独作为第一层,2单独作为第6层,中间有四层

为什么没有点与2同层呢,因为让一个点待在第五层一定比第六层优,待在第五层他可以和四五六层的连边,而在第六层只能和五六层的连边

那么,与1有边相连的一定是第二层,与2有边相连的一定是第五层,与第二层的有边相连有不是第一、二层的一定是第三层,与第五层有边相连又不是第五、六层的一定是第四层,那么还剩下一些层,我们可以把他们划分到第三层或第四层里,那肯定是如果第二层比第五层大就都划到第三层,否则就都划到第四层

然后就可以算答案了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 40010
#define MAXM 1000010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
int n,m;
int bel[MAXN];
int v1[MAXM],v2[MAXM];
ll siz[6];
int main(){
	/*
	freopen("tel.in","r",stdin);
	freopen("tel.out","w",stdout);
	//*/
	int i;
	scanf("%d%d",&n,&m);
	siz[0]=siz[5]=1;
	int TTT=0;
	for(i=1;i<=m;i++){
		scanf("%d%d",&v1[i],&v2[i]);
		if(v1[i]==1){
			bel[v2[i]]=1;
			
			TTT++;
		}
		if(v1[i]==2){
			bel[v2[i]]=4;
			TTT++;
		}
		if(v2[i]==1){
			bel[v1[i]]=1;
			TTT++;
		}
		if(v2[i]==2){
			TTT++;
			bel[v1[i]]=4;
		}
	}
	for(i=1;i<=m;i++){
		if(v1[i]!=1&&!bel[v1[i]]&&bel[v2[i]]==1){
			bel[v1[i]]=2;
		}
		if(v1[i]!=2&&!bel[v1[i]]&&bel[v2[i]]==4){
			bel[v1[i]]=3;
		}
		if(v2[i]!=1&&!bel[v2[i]]&&bel[v1[i]]==1){
			bel[v2[i]]=2;
		}
		if(v2[i]!=2&&!bel[v2[i]]&&bel[v1[i]]==4){
			bel[v2[i]]=3;
		}
	}
	for(i=1;i<=n;i++){
		if(bel[i]){
			siz[bel[i]]++;
		}
	}
	for(i=3;i<=n;i++){
		if(!bel[i]){
			if(siz[1]>siz[4]){
				siz[2]++;
			}else{
				siz[3]++;
			}
		}
	}
	ll ans=0;
	for(i=0;i<=4;i++){
		ans+=siz[i]*(siz[i]-1)/2;
		ans+=siz[i]*siz[i+1];
	}
	ans-=m;
	int T=siz[1]+siz[4];
	int TT=0;
	for(i=1;i<=m;i++){
		if(v1[i]==1||v1[i]==2||v2[i]==1||v2[i]==2){
			TT++;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

/*
10 10
1 3
3 5
5 7
7 9
2 9
1 4
4 6
6 8
8 10
2 10

6 5
1 3
3 4
4 5
5 6
6 2
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值