P13017 [GESP202506 七级] 线图

题目

传送门

思路

我们观察可以发现新建的这个图的结点是以边为结点,观察题目可以发现只要这个图任意两个结点的u或者v相等,那么我们就可以连接这两个结点。

怎么统计连接的条数?

我们可以遍历每一条边,然后寻找与他的u或者v相等的边,如何ans++,最后记得把ans/2。但是这样的时间复杂度达到了O(m^2),直接TLE。

优化

我们发现只要寻找重复出现的结点即可,所以我们可以统计所有边的u和v的数量,然后分别相加即可。

细节

  • ans要开long long
  • 每次相加之前都要减一

代码

有注释

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt[100005];
struct u{
	int u,v;
}a[100005];
long long ans=0; 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i].u>>a[i].v;
		cnt[a[i].u]++;//统计 
		cnt[a[i].v]++;
	}
	for(int i=1;i<=m;i++){
		cnt[a[i].u]--;//避免重复统计 
		cnt[a[i].v]--;
		ans+=cnt[a[i].u]+cnt[a[i].v];//相加 
	}
	cout<<ans;
	return 0;
} 

无注释

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt[100005];
struct u{
	int u,v;
}a[100005];
long long ans=0; 
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>a[i].u>>a[i].v;
		cnt[a[i].u]++;
		cnt[a[i].v]++;
	}
	for(int i=1;i<=m;i++){
		cnt[a[i].u]--;
		cnt[a[i].v]--;
		ans+=cnt[a[i].u]+cnt[a[i].v];
	}
	cout<<ans;
	return 0;
} 

另一个版本

我们枚举每一个结点,然后统计它相连的结点的数量,最后n*(n-1)/2即可

for(int i=1;i<=n;i++){
    int s=v[i].size();
    ans+=s*(s-1)/2;
}

完结撒花

posted @ 2026-08-31 15:26  陈晨2011  阅读(7)  评论(0)    收藏  举报