ABC218

D

统计矩形

典,矩形只需要对角线两个点就能确定,枚举一组对角线,ds判断另一组对角线是否存在。这样一个矩形会被两组对角线分别枚举到,最后除二

void solve(){
	int n;
	cin>>n;
	set<pii>s;
	vi x(n+1),y(n+1);
	rep(i,1,n){
		cin>>x[i]>>y[i];
		s.insert({x[i],y[i]});
	}
	int ans=0;
	rep(i,1,n){
		rep(j,i+1,n){
			if(x[i]==x[j]||y[i]==y[j])continue;
			if(s.count({x[j],y[i]})&&s.count({x[i],y[j]})){
				ans++;
			}
		}
	}
	cout<<ans/2;
}

E

给一个图,可以删除一些边,但必须联通,删边有正收益或负收益,问最大收益?

如果只有正收益,总收益就是所有边的收益之和,减去最后留下来的边的收益,想让总收益尽可能大,就要让留下来的边的收益尽可能小,这其实就是最小生成树。

对于负收益,选了,总收益会变小。把他留在图里,连通性不会更差,所以都留在图里不删除。

void solve(){
	int n,m;
	cin>>n>>m;
	vvi e;
	int ans=0;
	rep(i,1,m){
		int u,v,w;
		cin>>u>>v>>w;
		e.push_back({w,u,v});
		ans+=w;
	}
	
	sort(e.begin(),e.end());
	vi f(n+1);
	rep(i,1,n){
		f[i]=i;
	}
	auto &&find=[&](auto &&find,int x)->int{
		if(f[x]==x)return x;
		return f[x]=find(find,f[x]);
	};
	
	for(auto &t:e){
		int w=t[0],u=t[1],v=t[2];
		int fx=find(find,u),fy=find(find,v);
		if(w<0)ans-=w;
		if(fx!=fy){
			if(w>0)ans-=w;
			f[fx]=fy;
		}
	}
	cout<<ans;
}

F

一张图,对于删除每一条边的情况,求1到n的最短路

典,首先最短路有个结论,最短路上的边不会超过 n n n条,所以如果删除的不是最短路上的边,不会影响最短路,直接输出之前求出来的最短路。如果删除的是最短路上的边,重新跑一次最短路。

每次求最短路是 O ( n 2 ) O(n^2) O(n2),最多跑 O ( n ) O(n) O(n)次,总复杂度 O ( n 3 ) O(n^3) O(n3)

void solve(){
	int n,m;
	cin>>n>>m;
	vi u(m+1),v(m+1);
	vvi g(n+1);
	rep(i,1,m){
		cin>>u[i]>>v[i];
		g[u[i]].push_back(v[i]);
	}
	vi pre(n+1);
	auto cal=[&](int x,int y)->int{
		vi d(n+1,1e9);
		queue<int>q;
		q.push(1);
		d[1]=0;
		while(q.size()){
			int u=q.front();
			q.pop();
			
			for(int v:g[u]){
				if(u==x&&v==y)continue;
				if(d[v]>d[u]+1){
					d[v]=d[u]+1;
					pre[v]=u;
					q.push(v);
				}			
			}
		}
		return d[n];
	};
	int ans=cal(-1,-1);
	int cur=n;
	set<pii>s;
	while(cur!=1&&pre[cur]){
		s.insert({pre[cur],cur});
		cur=pre[cur];
	}
	rep(i,1,m){
		if(s.count({u[i],v[i]})){
			int res=cal(u[i],v[i]);
			if(res<1e9)cout<<res<<'\n';
			else cout<<-1<<'\n';
		}
		else{
			if(ans<1e9)cout<<ans<<'\n';
			else cout<<-1<<'\n';
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值