shjwudp

导航

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5452

题意:给你一个图和它的生成树,要你在树上删一条边,问你最少删多少条边使得图不联通(开始时图一定联通)

解:

对每一条非树边对它两点之间的树上链的边+1,答案就是树上边的最小边权+1。处理上开始用了树状数组=TLE,其实由于只查询一次,用数组维护一下就好

  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<<"\tup: "<<w[f1]<<"\t"<<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<<"\tup: "<<w[u]<<"\t"<<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\n", ++now, ans+1);
122     }
123     return 0;
124 }
View Code

 

posted on 2015-09-24 18:47  shjwudp  阅读(391)  评论(0编辑  收藏  举报