您的位置:首页 > 其它

【UVa 1670/Uvalive 5920】 Kingdom Roadmap 图论

2018-03-09 23:13 531 查看
老年人需要大一点的字体。
紫书习题11-17 NEERC2011
给定一棵树,然后让你加入尽量少的边,使得整张图双连通。
这个uva1670好像数据错了,非常难受,怎么搞都过不去,然后网上现有的题解都是各种奇技淫巧,非常奇怪。
所以自己想了想然后还是自己写了一个,虽然wa了无数次,最后还是在Uvalive5920获得了一个AC,也算是不枉花费的时间了。

先上代码:#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mem(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef pair<int,int> pii;

const int mn=1e5+5;

int n,root;
int f[mn];
vector<int> g[mn],son[mn],leaf;
vector<pii> ans;

void dfs(int x,int fa){
f[x]=fa;
for(auto i:g[x]){
if (i==fa) continue;
dfs(i,x);
}
if (g[x].size()==1){
leaf.pb(x);
if (leaf.size()==3){
int u=leaf[1];
ans.pb(pii(leaf[0],x));
leaf.clear();
leaf.pb(u);
}
}
}

int main() {
while(~scanf("%d",&n)){
ans.clear();
for(int i=1;i<=n;i++) g[i].clear(),son[i].clear(),f[i]=0;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].pb(v);
g[v].pb(u);
}
if (n==2){
puts("1\n1 2");
}
for(int i=1;i<=n;i++){
if (g[i].size()>1) {
root=i;
break;
}
}
dfs(root,0);
if (leaf.size()==2) {
int u=leaf.back();
int v=*leaf.begin();
leaf.clear();
ans.pb(pii(u,v));
}
for(int i:leaf) ans.pb(pii(root,i));
leaf.clear();
//answer
printf("%d\n",ans.size());
for(auto i:ans) printf("%d %d\n",i.first,i.second);
}
return 0;
}我们先随便选一个度数大于2的点作为树根,然后从该树根延展出去。
显然,直接延展出去的每一条边都是一座桥。
为了去除连接每棵子树的根到更上层的桥,每棵子树应该预留下一个点(连上去),所以每棵子树都要留一个点或者两个点(三个点的时候就可以连接两个点了),这样一步步上去,搞搞好就ac辣。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法竞赛