题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5452
题意:给你一个图和它的生成树,要你在树上删一条边,问你最少删多少条边使得图不联通(开始时图一定联通)
解:
对每一条非树边对它两点之间的树上链的边+1,答案就是树上边的最小边权+1。处理上开始用了树状数组=TLE,其实由于只查询一次,用数组维护一下就好
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 * Problem: 3 * Author: SHJWUDP 4 * Created Time: 2015/9/23 星期三 19:32:28 5 * File Name: 1001.cpp 6 * State: 7 * Memo: 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <algorithm> 14 15 using namespace std; 16 17 struct Graph { 18 struct Edge { 19 int u, v; 20 }; 21 int n, m; 22 vector<Edge> edges; 23 vector<vector<int>> G; 24 Graph(int _n):n(_n), G(_n){} 25 void addEdge(int u, int v) { 26 edges.push_back({u, v}); 27 m=edges.size(); 28 G[u].push_back(m-1); 29 } 30 vector<int>& operator[](int x) { 31 return G[x]; 32 } 33 }; 34 35 struct LinkCutTree { 36 Graph G; 37 vector<int> fa, siz, son, dep, top; 38 vector<int> w; 39 int id; 40 vector<int> ans; 41 LinkCutTree(int n):G(n){} 42 void init() { 43 fa.resize(G.n); 44 siz.resize(G.n); 45 son.resize(G.n); 46 dep.resize(G.n); 47 top.resize(G.n); 48 w.resize(G.n); 49 id=0; 50 51 int root=1; 52 fa[root]=-1; 53 dfs1(root, 0); 54 dfs2(root, root); 55 ans.assign(G.n+7, 0); 56 } 57 int dfs1(int u, int d) { 58 siz[u]=1; dep[u]=d; son[u]=-1; 59 for(auto i : G[u]) { 60 const auto& e=G.edges[i]; 61 if(e.v==fa[u]) continue; 62 fa[e.v]=u; 63 siz[u]+=dfs1(e.v, d+1); 64 if(son[u]==-1 || siz[son[u]]<siz[e.v]) son[u]=e.v; 65 } 66 return siz[u]; 67 } 68 void dfs2(int u, int tp) { 69 w[u]=id++; top[u]=tp; 70 if(son[u]!=-1) dfs2(son[u], tp); 71 for(auto i : G[u]) { 72 const auto & e=G.edges[i]; 73 if(e.v==fa[u] || e.v==son[u]) continue; 74 dfs2(e.v, e.v); 75 } 76 } 77 void update(int u, int v) { 78 int f1=top[u], f2=top[v]; 79 while(f1!=f2) { 80 if(dep[f1]<dep[f2]) swap(f1, f2), swap(u, v); 81 // cout<<" up: "<<w[f1]<<" "<<w[u]+1<<endl; 82 ++ans[w[f1]]; --ans[w[u]+1]; 83 u=fa[f1]; f1=top[u]; 84 } 85 if(u==v) return; 86 if(dep[u]>dep[v]) swap(u, v); 87 // cout<<" up: "<<w[u]<<" "<<w[v]<<endl; 88 ++ans[w[son[u]]]; --ans[w[v]+1]; 89 } 90 }; 91 92 int n, m; 93 int main() { 94 #ifndef ONLINE_JUDGE 95 freopen("in", "r", stdin); 96 //freopen("out", "w", stdout); 97 #endif 98 int T, now=0; 99 scanf("%d", &T); 100 while(T--) { 101 scanf("%d%d", &n, &m); 102 LinkCutTree lct(n+1); 103 Graph & G=lct.G; 104 for(int i=0; i<n-1; ++i) { 105 int a, b; 106 scanf("%d%d", &a, &b); 107 G.addEdge(a, b); 108 G.addEdge(b, a); 109 } 110 lct.init(); 111 for(int i=n-1; i<m; ++i) { 112 int a, b; 113 scanf("%d%d", &a, &b); 114 lct.update(a, b); 115 } 116 int ans=0x7f7f7f7f; 117 for(int i=1; i<n; ++i) { 118 lct.ans[i]+=lct.ans[i-1]; 119 ans=min(ans, lct.ans[i]); 120 } 121 printf("Case #%d: %d ", ++now, ans+1); 122 } 123 return 0; 124 }