A1003
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=510;
int d[maxn][maxn],w[maxn];
int dist[maxn],cnt[maxn],sum[maxn];
int n,m,S,T;
bool st[maxn]={false};
void dijkstra()
{
memset(dist, 0x3f, sizeof dist); //对dist进行 初始化 为 0x3f
dist[S]=0,cnt[S]=1,sum[S]=w[S]; //到起点S的最短距离是0 ,路径条数设置为1,同时到起点的 点权就是 w对应的点权
for(int i=0; i<n; i++)
{
int t=-1; //在dist中,找到 距离 最小的点 其实 t就是 中转点
for(int j=0; j<n; j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true; //对t进行 标记
for(int j=0; j<n; j++) //遍历n个点
{
if(dist[j]>dist[t]+d[t][j]) //如果 t是 更小的点 更新 最短路径 和 最短路径的 条数 及 边权
{
dist[j]=dist[t]+d[t][j];
cnt[j]=cnt[t];
sum[j]=sum[t]+w[j];
}
else if(dist[j]==dist[t]+d[t][j]) //如果路径相同 直接加等于,然后 更新最大边权
{
cnt[j]+=cnt[t];
sum[j]=max(sum[j],sum[t]+w[j]);
}
}
}
}
int main()
{
cin >> n >> m >> S >> T;
for (int i = 0; i < n; i ++ ) cin >> w[i]; //w表示 点 权
memset(d, 0x3f, sizeof d); //将边权 也初始化为 0x3f
while (m -- )
{
int a, b, c;
cin >> a >> b >> c;
d[a][b] = d[b][a] = c; //因为是 无向图,设置为双向
}
dijkstra();
cout << cnt[T] << ' ' << sum[T] << endl;
return 0;
}
A1030
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=510;
int d[maxn][maxn],w[maxn][maxn];
int pre[maxn];
int dist[maxn],sum[maxn];
bool st[maxn]={false};
int n,m,S,T;
void print(int x)
{
if(x==S)
{
cout << S << " ";
return ;
}
print(pre[x]);
cout << x << " ";
}
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
memset(sum,0x3f,sizeof sum);
dist[S]=0,sum[S]=0;
for(int i=0; i<n; i++)
{
int t=-1;
for(int j=0; j<n; j++)
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
t=j;
}
st[t]=true;
for(int j=0; j<n; j++)
{
if(dist[j]>dist[t]+d[t][j])
{
dist[j]=dist[t]+d[t][j];
sum[j]=sum[t]+w[t][j];
pre[j]=t;
}
else if(dist[j]==dist[t]+d[t][j])
{
if(sum[j]>sum[t]+w[t][j])
{
sum[j]=sum[t]+w[t][j];
pre[j]=t;
}
}
}
}
}
int main()
{
cin >> n >> m >> S >> T;
memset(d,0x3f,sizeof d);
for(int i=0; i<m; i++)
{
int a,b,c,k;
cin >> a >> b >> c >> k;
d[a][b]=d[b][a]=c;
w[a][b]=w[b][a]=k;
}
dijkstra();
print(T);
cout << dist[T] << " " << sum[T] << endl;
}
A1087
#include<iostream>
#include<unordered_map>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=210;
int n,m,S,T;
unordered_map<string,int> mp;
int w[maxn],d[maxn][maxn],dist[maxn],cnt[maxn],cost[maxn],sum[maxn]; //最短路径条数 最短路径 点权值 路径上的个数
int pre[maxn];
bool st[maxn]={false};
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0,cnt[1]=1;
for(int i=0; i<n; i++) //这个for表示 n个节点 循环n-1次
{
int t=-1;
for(int j=1; j<=n; j++) //表示遍历每一个点的下标
{
if(st[j]==false && (t==-1 || dist[t]>dist[j]))
{
t=j;
}
}
st[t]=true;
for(int j=1; j<=n; j++) //遍历n个点
{
if(dist[j]>dist[t]+d[t][j])
{
dist[j]=dist[t]+d[t][j];
cnt[j]=cnt[t];
cost[j]=cost[t]+w[j];
sum[j]=sum[t]+1;
pre[j]=t;
}
else if(dist[j]==dist[t]+d[t][j])
{
cnt[j]+=cnt[t]; //路径相同直接 加 不需要任何 条件
if(cost[j]<cost[t]+w[j]) //需要找到 最大的 幸福指数
{
cost[j]=cost[t]+w[j];
sum[j]=sum[t]+1;
pre[j]=t;
}
else if(cost[j]==cost[t]+w[j])
{
if(sum[j]>sum[t]+1)
{
sum[j]=sum[t]+1;
pre[j]=t;
}
}
}
}
}
}
int main()
{
string city[maxn];
cin >> n >> m >> city[1];
mp[city[1]]=1;
for(int i=2; i<=n; i++)
{
cin >> city[i] >> w[i];
mp[city[i]]=i;
}
memset(d,0x3f,sizeof d);
for(int i=0; i<m; i++)
{
string a,b;
int c;
cin >> a >> b >> c;
int aa=mp[a],bb=mp[b];
d[aa][bb]=d[bb][aa]=c;
}
T=mp["ROM"];
dijkstra();
cout << cnt[T] << " " << dist[T] << " " << cost[T] << " " << cost[T]/sum[T] << endl;
vector<int> path;
for(int i=T; i!=1; i=pre[i])
path.push_back(i);
cout << city[1];
for(int i=path.size()-1; i>=0; i--)
{
cout << "->" << city[path[i]];
}
return 0;
}
A1122
#include <iostream>
#include <cstring>
using namespace std;
const int N = 210;
int n, m;
bool g[N][N], st[N];
int nodes[N * 2];
bool check(int cnt)
{
if (nodes[0] != nodes[cnt - 1] || cnt != n + 1) return false;
memset(st, 0, sizeof st);
for (int i = 0; i < cnt - 1; i ++ )
{
st[nodes[i]] = true;
if (g[nodes[i]][nodes[i + 1]]==false)
return false;
}
for (int i = 1; i <= n; i ++ )
if (st[i]==false)
return false;
return true;
}
int main()
{
cin >> n >> m;
while (m -- )
{
int a, b;
cin >> a >> b;
g[a][b] = g[b][a] = true;
}
int k;
cin >> k;
while (k -- )
{
int cnt;
cin >> cnt;
for (int i = 0; i < cnt; i ++ ) cin >> nodes[i];
if (check(cnt)) puts("YES");
else puts("NO");
}
return 0;
}
A1126
#include<iostream>
using namespace std;
/*
欧拉回路:1.连通 2.偶度数点的个数为n
半欧拉回路:1.连通 2.奇度数的点的个数为2 偶度数点的个数为n-2
剩下情况,不是欧拉回路
*/
const int maxn=510;
bool st[maxn],g[maxn][maxn];
int n,m,d[maxn];
int dfs(int x) //通过dfs来判断 是否是 联通图
{
st[x]=true;
int res=1;
for(int i=1; i<=n; i++)
{
if(st[i]==false && g[x][i]==true)
res+=dfs(i);
}
return res;
}
int main()
{
cin >> n >> m;
while(m--)
{
int a,b;
cin >> a >> b;
g[a][b]=g[b][a]=true;
d[a]++,d[b]++;
}
for(int i=1; i<=n; i++)
{
if(i!=1)
cout << " ";
cout << d[i];
}
cout << endl;
if(dfs(1)==n) //判断该 图是否为联通的
{
int res=0;
for(int i=1; i<=n; i++)
{
if(d[i]%2==0)
res++;
}
if(res==n)
cout << "Eulerian" << endl;
else if(res+2==n)
cout << "Semi-Eulerian" << endl;
else
cout << "Non-Eulerian" << endl;
}
else
{
cout << "Non-Eulerian" << endl;
}
return 0;
}
A1131(优化版)
/*
这道题首先 要找到 最小的站点停靠数量+最少的换乘次数
对应的话 就是 最短路径+最少的交叉路口
这道题基本上也就是 Dijkstra优化版本 模板
*/
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1000010;
int n,idx;
int stop[maxn];
int e[maxn],w[maxn],line[maxn],h[maxn],ne[maxn],dist[maxn],cnt[maxn],pre[maxn];
string Info[maxn];
bool st[maxn];
typedef pair<int,int> PII;
void add(int a,int b,int c,int d) //add(stop[j],stop[k],len,T)
{
e[idx]=b,w[idx]=c,line[idx]=d,ne[idx]=h[a],h[a]=idx++; //e[i]表示下一个 节点,w表示从起点到idx的权值,line表示idx这个点是哪条线
}
string getNum(int x)
{
char res[5];
sprintf(res,"%04d",x);
return res;
}
void dijkstra(int start,int end)
{
memset(dist,0x3f,sizeof dist);
memset(cnt,0x3f,sizeof cnt);
memset(st,false,sizeof st);
dist[start]=cnt[start]=0;
priority_queue<PII,vector<PII>,greater<PII>> heap; //小根堆
heap.push({0,start});
while(!heap.empty())
{
auto t=heap.top();
heap.pop();
int vers=t.second;
if(vers==end)
break;
if(st[vers])
continue;
st[vers]=true;
for(int i=h[vers]; i!=-1; i=ne[i])
{
int j=e[i];
if(dist[j]>dist[vers]+w[i]) //最短路径
{
dist[j]=dist[vers]+w[i];
cnt[j]=cnt[vers]+1;
pre[j]=vers;
Info[j]="Take Line#" + to_string(line[i]) + " from " + getNum(vers) + " to " + getNum(j) + ".";
heap.push({dist[j],j});
}
else if(dist[j]==dist[vers]+w[i])
{
if(cnt[j]>cnt[vers]+1) //通过 最少的 点数
{
cnt[j]=cnt[vers]+1;
pre[j]=vers;
Info[j]="Take Line#" + to_string(line[i]) + " from " + getNum(vers) + " to " + getNum(j) + ".";
}
}
}
}
cout << dist[end] << endl;
vector<string> path;
for(int i=end; i!=start; i=pre[i])
{
path.push_back(Info[i]);
}
for(int i=path.size()-1; i>=0; i--)
{
cout << path[i] << endl;
}
}
int main()
{
cin >> n; //输入n个点
int m; //m条边
memset(h,-1,sizeof(h)); //对h初始化为-1
for(int T=1; T<=n; T++)
{
cin >> m; //输入站的个数
for(int i=0; i<m; i++)
{
cin >> stop[i];
}
for(int j=0; j<m; j++) //将所有的点连接成一条边
{
for(int k=0; k<j; k++)
{
int len;
if(stop[0]!=stop[m-1]) //如果 这条 不是 一条环路
len=j-k;
else //如果这条线 是一条 环路
{
len=min(j-k,k+m-1-j);
}
add(stop[j],stop[k],len,T);
add(stop[k],stop[j],len,T);
}
}
}
int k;
cin >> k;
int start,end;
while(k--)
{
cin >> start >> end;
dijkstra(start,end);
}
}
A1134
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=10100;
int n,m;
/*
题目的思路是通过点来观察,边是否都存在;解题思路是通过 遍历每一条边来观察 该条边上的 两个点是否存在
*/
struct node
{
int a,b;
}Node[maxn];
bool st[maxn];
int main()
{
cin >> n >> m;
for(int i=0; i<m; i++)
{
cin >> Node[i].a >> Node[i].b;
}
int k;
cin >> k;
while(k--)
{
int cnt;
cin >> cnt;
memset(st,false,sizeof st);
for(int i=0; i<cnt; i++)
{
int temp;
cin >> temp;
st[temp]=true;
}
int i;
for(i=0; i<m; i++)
{
if(st[Node[i].a]==false && st[Node[i].b]==false)
break;
}
if(i==m)
{
cout << "Yes" << endl;
}
else
cout << "No" << endl;
}
return 0;
}
A1142
#include<iostream>
using namespace std;
const int maxn=310;
int n,m;
int g[maxn][maxn];
int vers[maxn];
bool isClique(int cnt)
{
for(int i=0; i<cnt; i++)
for(int j=0; j<i; j++)
{
if(g[vers[i]][vers[j]]==false)
return false;
}
return true;
}
bool isMaximal(int cnt)
{
bool st[maxn]={false};
for(int i=0; i<cnt; i++)
st[vers[i]]=true;
for(int i=1; i<=n; i++)
{
bool success=true;
if(st[i]==false)
{
for(int j=0; j<cnt; j++)
{
if(g[i][vers[j]]==false)
{
success=false;
break;
}
}
if(success)
{
return false;
}
}
}
return true;
}
int main()
{
cin >> n >> m;
for(int i=0; i<m; i++)
{
int a,b;
cin >> a >> b;
g[a][b]=g[b][a]=true;
}
int k;
cin >> k;
for(int i=0; i<k; i++)
{
int cnt;
cin >> cnt;
for(int j=0; j<cnt; j++)
{
cin >> vers[j];
}
if(isClique(cnt))
{
if(isMaximal(cnt))
{
cout << "Yes" << endl;
}
else
cout << "Not Maximal" << endl;
}
else
cout << "Not a Clique" << endl;
}
}
A1146
#include<iostream>
using namespace std;
const int maxn=10010;
struct node
{
int a,b;
}Node[maxn];
int n,m;
int main()
{
cin >> n >> m;
for(int i=0; i<m; i++)
{
cin >> Node[i].a >> Node[i].b;
}
int k;
cin >> k;
int inq=1;
for(int i=0; i<k; i++)
{
int vers[maxn];
bool success=true;
for(int j=1; j<=n; j++)
{
int temp;
cin >> temp;
vers[temp]=j;
}
for(int i=0; i<m; i++)
{
if(vers[Node[i].a]>vers[Node[i].b])
{
success=false;
break;
}
}
if(success==false)
{
if(inq!=1)
cout << " ";
cout << i;
inq++;
}
}
return 0;
}
A1150
/*
这道题就是统计两个点之间的距离
不是环路 简单环路 环路
1.有的点没有访问 访问的点数为n+1 访问点数不是n+1
2.两个点之间没有路径
*/
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=222;
const int INF=0x3f3f3f3f;
int G[maxn][maxn];
int n,m,k;
int main()
{
fill(G[0],G[0]+maxn*maxn,INF); //对G进行初始化
cin >> n >> m;
int temp1,temp2,temp3;
for(int i=0; i<m; i++)
{
cin >> temp1 >> temp2 >> temp3;
G[temp1][temp2]=G[temp2][temp1]=temp3;
}
cin >> k;
int temp4;
int min_dis=INF,min_id;
for(int T=1; T<=k; T++)
{
int vers[maxn];
bool st[maxn]={false},success=true;
int sum=0;
cin >> temp4;
for(int i=0; i<temp4; i++)
{
cin >> vers[i];
st[vers[i]]=true;
}
for(int j=0; j+1<temp4; j++)
{
int a=vers[j],b=vers[j+1];
if(G[a][b]==INF) //如果两个点之间没有路,说明不是一个环路
{
sum=-1;
break;
}
else
{
sum+=G[a][b]; //否则统计 两个 点 之间的 距离
}
}
if(vers[0]!=vers[temp4-1]) //始终点不一样,不是一个环路
success=false;
for(int k=1; k<=n; k++) //有的点没有访问到
{
if(st[k]==false)
{
success=false;
break;
}
}
if(sum==-1)
{
printf("Path %d: NA (Not a TS cycle)\n",T);
}
else
{
if(success==false)
{
printf("Path %d: %d (Not a TS cycle)\n",T,sum);
}
else
{
if(temp4==n+1)
{
printf("Path %d: %d (TS simple cycle)\n",T,sum);
}
else
{
printf("Path %d: %d (TS cycle)\n",T,sum);
}
if(min_dis>sum)
{
min_dis=sum;
min_id=T;
}
}
}
}
printf("Shortest Dist(%d) = %d\n",min_id,min_dis);
return 0;
}
A1154
#include<iostream>
#include<set>
using namespace std;
const int maxn=10111;
int n,m;
struct node
{
int a,b;
}Node[maxn];
int main()
{
cin >> n >> m;
for(int i=0; i<m; i++)
{
cin >> Node[i].a >> Node[i].b;
}
int k;
cin >> k;
while(k--)
{
set<int> color;
int color1[maxn];
bool st[maxn]={false};
bool success=true;
int res=0;
for(int i=0; i<n; i++)
{
int temp;
cin >> temp;
color.insert(temp);
color1[i]=temp;
}
for(int i=0; i<m; i++)
{
if(color1[Node[i].a]==color1[Node[i].b])
{
cout << "No" << endl;
success=false;
break;
}
}
if(success)
cout << color.size() << "-coloring" << endl;
}
return 0;
}
A1018
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int C, n, S, m;
int c[N];
int g[N][N];
int dist[N];
bool st[N];
vector<int> path, ans;
int send = INF, bring = INF;
void dijkstra() //相当于将dist最短路径铺好
{
memset(dist, 0x3f, sizeof dist);
dist[S] = 0;
for (int i = 0; i < n; i ++ )
{
int t = -1;
for (int j = 0; j <= n; j ++ )
if (!st[j] && (t == -1 || dist[j] < dist[t]))
t = j;
st[t] = true;
for (int j = 0; j <= n; j ++ )
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
}
//s表示当前 需要 带去 多少量 自行车?
void dfs(int u, int s, int mins) //当前走到u,当前总和是s,当前最小值是mins
{
if (u) //除了起点之外,对s和mins进行更新
{
s -= (C + 1) / 2 - c[u]; //这个s就是 根据 每一条路径 计算出来 到达下一个站点的值
mins = min(mins, s); //mins就是不断统计 s最小值,表示需要自行车最多的那种情况,最终这个mins表示的就是从PBMS中 运过来的 自行车的 数量
}
if (u == S) //刚好走完 最短路径中 的 其中 一条时,来判断一下他的值
{
int sd = abs(min(mins, 0)); //mins小于0,表示需要带mins辆车,如果mins》0,表示带0辆车
int bg = s + sd;
if (sd < send) ans = path, send = sd, bring = bg; //需要找到最小的send和bring的值,其中sd和bg都是临时的
else if (sd == send && bg < bring) ans = path, bring = bg;
return;
}
for (int i = 1; i <= n; i ++ ) //遍历一下从u出发的所有边
if (dist[u] == g[u][i] + dist[i]) //必须是在最短路径中,所以才会有这个if判断
{
path.push_back(i);
dfs(i, s, mins);
path.pop_back();
}
}
int main()
{
cin >> C >> n >> S >> m;
for (int i = 1; i <= n; i ++ ) cin >> c[i]; //c表示每个 站点 自行车的 情况
memset(g, 0x3f, sizeof g); //将g调整为最大值
for (int i = 0; i < m; i ++ )
{
int x, y, z;
cin >> x >> y >> z;
g[x][y] = g[y][x] = z;
}
dijkstra();
path.push_back(0);
dfs(0, 0, 0); //从起点出发,最开始一辆自行车都不带,中间最小值为0
cout << send << ' ' << 0; //send表示带去的数量
for (int i = 1; i < ans.size(); i ++ ) //ans存放最后的路径
cout << "->" << ans[i];
cout << " " << bring << endl; //bring存放 带回去的自行车数量
return 0;
}
A1072
/*
给出加油站和居民区的 距离,选择一个合适的加油站,满足一下条件:
1.要求所选加油站尽可能 远离 居民区,所以 必须 满足 距离 该 加油站最近的 居民区 距离 最远
2.要求 所有的 居民区 都在 范围之内
3.该加油站 到达 所有的 居民区 的 距离 最小
如果 上面 条件 都 相同,则需要 输出 最小的 加油站 编号
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1020, INF = 0x3f3f3f3f;
int n, m, k, D;
int g[N][N];
int dist[N];
bool st[N];
int get(string s) //将所有的加油站的编号设置为 n+1
{
if (s[0] == 'G') return n + stoi(s.substr(1));
return stoi(s);
}
void dijkstra(int start, int &mind, int &sumd)
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[start] = 0;
for (int i = 0; i < n + m; i ++ )
{
int t = -1;
for (int j = 1; j <= n + m; j ++ )
if (!st[j] && (t == -1 || dist[j] < dist[t]))
t = j;
st[t] = true;
for (int j = 1; j <= n + m; j ++ ) //从 每个 加油站 出发,求出 他 所能 到达 的 最小距离
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
for (int i = 1; i <= n; i ++ )
if (dist[i] > D) //如果 距离 超出了 范围D 则 设置mind为-INF
{
mind = -INF;
return;
}
mind = INF, sumd = 0;
for (int i = 1; i <= n; i ++ ) //遍历 n个 居民区
{
mind = min(mind, dist[i]); //前面 这个 值,必须 找到mind的最小值
sumd += dist[i];
}
}
int main()
{
cin >> n >> m >> k >> D;
memset(g, 0x3f, sizeof g);
while (k -- )
{
string a, b;
int z;
cin >> a >> b >> z;
int x = get(a), y = get(b);
g[x][y] = g[y][x] =z;
}
//最后输出的是 加油站 到达 居民区的 和的平均距离
int res = -1, mind = 0, sumd = INF; //res表示合适加油站的编号,mind表示距离加油站最近的最大距离,sumd表示该加油站到达 所有 局民区 的总的距离
for (int i = n + 1; i <= n + m; i ++ ) //遍历m个加油站
{
int d1, d2;
dijkstra(i, d1, d2); //从每个 加油站 出发
if (d1 > mind) res = i, mind = d1, sumd = d2; //这里 需要的是 最大 的 mind,如果 超出了 范围,则直接 mind=-INF,所以 当INF为 负的INF时,自然不用 理会
else if (d1 == mind && d2 < sumd) res = i, sumd = d2;
}
if (res == -1) puts("No Solution");
else printf("G%d\n%.1lf %.1lf\n", res - n, (double)mind, (double)sumd / n);
return 0;
}
A1076
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1010, M = 100010; //n的值 小于等于1000 每个点后面的个数小于等于100 所以最多有10^6条边
int n, m;
int h[N], e[M], ne[M], idx; //邻接表 来 存储 数据 e和ne都根 边 有关
bool st[N];
void add(int a, int b) //模板函数
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int bfs(int start) //宽搜
{
queue<int> q;
memset(st, 0, sizeof st); //有k次询问,然后 每次将 st的值 设置为 false
q.push(start);
st[start] = true; //将 起点 进行 一个 标记
int res = 0;
for (int step = 0; step < m; step ++ )
{
int sz = q.size(); //表示 每层 有多少个 点
res += sz;
for (int i = 0; i < sz; i ++ ) //需要 遍历 该层中的 每一个值
{
int t = q.front();
q.pop();
for (int j = h[t]; j!=-1; j = ne[j])
{
int k = e[j];
if (!st[k])
{
st[k] = true;
q.push(k);
}
}
}
}
return res + q.size() - 1; // 按照 题目 意思 比如 统计 前3层,实际上的 代码 统计 0,1,2层,需要统计的是1,2,3,q.size表示一层的人数,减1,其实表示第0层的一次
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ )
{
int cnt;
scanf("%d", &cnt);
while (cnt -- )
{
int x;
scanf("%d", &x);
add(x, i); //x是i的粉丝,添加一条从x到i的距离
}
}
int k;
scanf("%d", &k);
while (k -- )
{
int x;
scanf("%d", &x);
printf("%d\n", bfs(x));
}
return 0;
}
A1021
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
/*
这个题的思路就是 通过
1.并查集 求出 联通块数
2.用邻接表存储数据,然后通过遍历 每个点,求出最大深度,就势将i存储起来
*/
const int N = 10010, M = N * 2;
int n;
int h[N], e[M], ne[M], idx;
int p[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int dfs(int u, int father) //u表示 对应的 节点 father表示根
{
int depth = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i]; //j就是i的子节点
if (j == father) continue; //表示走了 回头路
depth = max(depth, dfs(j, u) + 1);
}
return depth;
}
int main()
{
cin >> n;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ ) p[i] = i;
int k = n;
for (int i = 0; i < n - 1; i ++ )
{
int a, b;
cin >> a >> b;
if (find(a) != find(b))
{
k -- ;
p[find(a)] = find(b);
}
add(a, b), add(b, a);
}
if (k > 1) printf("Error: %d components", k);
else
{
vector<int> nodes;
int max_depth = -1;
for (int i = 1; i <= n; i ++ )
{
int depth = dfs(i, -1); //从第i个节点 向下 搜索
if (depth > max_depth)
{
max_depth = depth;
nodes.clear();
nodes.push_back(i);
}
else if (depth == max_depth)
nodes.push_back(i);
}
for (auto v : nodes) cout << v << endl;
}
return 0;
}