【2月7日-2月10日PAT刷题笔记】——图算法专题 图的遍历

图的遍历

1013 Battle Over Cities (25分)

1021 Deepest Root (25分)

1034 Head of a Gang (30分)

1076 Forwards on Weibo (30分)

                                               1013 Battle Over Cities (25分)

题意:给出一个无向图,再给出k次询问,每次询问删除图中的一个顶点和他相关联的边。要求对于每次删掉这个节点后,还需要修几条路,才能使该无向图仍然保持是一个连通图

思路:DFS求出联通块个数,连通块个数减去1就是要修的路的条数

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
vector<int>ve[1005];
int vis[1005];
void dfs(int root) {
	if(vis[root]) return;
	vis[root]=1;
	for(int i=0; i<ve[root].size(); i++) {
		dfs(ve[root][i]);
	}
}
int main() {
	int a,b;
	cin>>n>>m>>k;
	while(m--) {
		scanf("%d%d",&a,&b);
		ve[a].push_back(b);
		ve[b].push_back(a);
	}
	int city;
	while(k--) {
		memset(vis,0,sizeof(vis));
		int num=0;
		scanf("%d",&city);
		vis[city]=1;
		for(int i=1; i<=n; i++) {
			if(!vis[i]) {
				dfs(i);
				num++;
			}

		}
		printf("%d\n",num-1);
    }
	return 0;
}

                                                1021 Deepest Root (25分)

题意:给出n个顶点和n-1条边,问:它们能否形成一个n个顶点的树?如果能,则从中选出节点作为树根,使得整棵树的高度最大。输出所有满足要求的可以作为树根的节点。

思路:先dfs求一下连通块个数,如果不为1,证明不能形成一棵树,输出“Error: %d components”如果唯一,再从每个顶点出发,再dfs求最大深度,同时记录答案个数

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+100;
vector<int>ve[maxn];
int vis[maxn],maxdepth=-1;
vector<int>ans;
void dfs(int root,int depth){
	if(vis[root]) return;
	vis[root]=1;
	if(depth>maxdepth) maxdepth=depth;
	for(int i=0;i<ve[root].size();i++) dfs(ve[root][i],depth+1);
}
int main(){
	int n,a,b;
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		scanf("%d%d",&a,&b);
		ve[a].push_back(b);
		ve[b].push_back(a);
	}	
	int cnt=0,res=-1;
	for(int i=1;i<=n;i++){
		if(!vis[i]) dfs(i,1),cnt++;
	}
	if(cnt!=1){
		printf("Error: %d components\n",cnt);
		return 0;
	}
	maxdepth=-1;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++){
		maxdepth=-1;
		memset(vis,0,sizeof(vis));
		dfs(i,1);
		if(maxdepth==res) ans.push_back(i);
		if(maxdepth>res) res=maxdepth,ans.clear(),ans.push_back(i);
	}
	sort(ans.begin(),ans.end());
	for(int i=0;i<ans.size();i++) printf("%d\n",ans[i]);
	if(cnt==1)
	return 0;
}

                                             1034 Head of a Gang (30分)

题意:给出若干人的通话记录,最后要求给出圈子的个数和圈子的头目(头目是指圈子当中通话时间最长的人)

思路:我用的并查集写的

#include<bits/stdc++.h>
using namespace std;
int n,k,pre[100005],times[100005],w[100005],cnt[100005];
map<string,int>mp1;
map<int,string>mp2;
struct node {
	string ID;
	int num;
	bool operator < (const node &a )const {
		return ID<a.ID;
	}
} b;
void init() {
	for(int i=0; i<100005; i++) pre[i]=i;
}
int fin(int x) {
	if(x==pre[x]) return x;
	else return pre[x]=fin(pre[x]);
}
void merge(int a,int b) {
	int aa=fin(a);
	int bb=fin(b);
	if(aa!=bb) {
		pre[aa]=bb;
	}
}

int main() {
	set<node>st;
	int weight,num1,num2,pointers=1;
	string str1,str2;
	init();
	cin>>n>>k;
	while(n--) {
		cin>>str1>>str2>>weight;
		if(!mp1[str1]) mp1[str1]=pointers++,num1=mp1[str1],mp2[num1]=str1;
		else num1=mp1[str1];
		if(!mp1[str2]) mp1[str2]=pointers++,num2=mp1[str2],mp2[num2]=str2;
		else num2=mp1[str2];
		times[num1]+=weight;
		times[num2]+=weight;
		merge(num1,num2);
		
	}
	for(int i=1;i<pointers;i++){
		int father=fin(i);
		if(times[i]>times[father]) pre[father]=i,pre[i]=i;
	}
	for(int i=1; i<pointers; i++) {
		int father=fin(i);
		cnt[father]++;
		if(i!=father) times[father]+=times[i];
	}
	for(int i=1; i<pointers; i++) {
		int father=fin(i);
		if(father==i&&cnt[i]>2&&times[i]/2>k) {
		//	cout<<times[i]<<" "<<k<<endl;
			b.ID=mp2[i];
			b.num=cnt[i];
			st.insert(b);
		}
	}
	cout<<st.size()<<endl;
	for(set<node>::iterator it=st.begin(); it!=st.end(); it++) {
		node C=*it;
		cout<<C.ID<<" "<<C.num<<endl;
	}
	return 0;
}

                                          1076 Forwards on Weibo (30分)

题意:给出有向图的节点和路的信息,求在转发层数上限内最多会被多少用户转发

思路:反正我不会=_=BFS,看了题就之后还是很简单的

#include<bits/stdc++.h>
using namespace std;
int n,l,k,query;
int vis[1005];
vector<int>ve[1005];
struct node{
	int layer;
	int ID;
};
int bfs(int start){
	int num=0;
	queue<node>que;
	node a,nx;
	a.ID=start;
	a.layer=0;
	que.push(a);
	vis[a.ID]=1;
	while(!que.empty()){
		a=que.front();
		que.pop();
		if(a.layer==l) break;
		for(int i=0;i<ve[a.ID].size();i++){
			nx.ID=ve[a.ID][i];
			nx.layer=a.layer+1;
			if(vis[nx.ID]) continue;
			vis[nx.ID]=1;
			num++;
			que.push(nx);
		}
	}
	return num;
}
int main(){
	int num,child;
	cin>>n>>l;
	for(int i=1;i<=n;i++){
		scanf("%d",&num);
		while(num--){
			scanf("%d",&child);
			ve[child].push_back(i);
		}
	}
	cin>>k;
	while(k--){
		memset(vis,0,sizeof(vis));
		scanf("%d",&query);
		int ans=bfs(query);
		printf("%d\n",ans); 
	}	
	
	return 0;
}
原创文章 70 获赞 25 访问量 7164

猜你喜欢

转载自blog.csdn.net/weixin_43727229/article/details/104255497