图的遍历
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&×[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;
}