CodeForces - 613D Kingdom and its Cities(虚树+贪心)
生活随笔
收集整理的這篇文章主要介紹了
CodeForces - 613D Kingdom and its Cities(虚树+贪心)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一棵 n 個結點組成的樹,有多組詢問,每組詢問給出 k 個點,現在可以刪除不同于 k 個節點的 m 個節點,使得這 k 個節點兩兩不連通,要求最小化 m ,如果不可能輸出 -1 ,每組詢問之間相互獨立
題目分析:如果只有一組樣例的話樹上貪心 O( n ) 就可以搞定,但是因為給了 T 組樣例,所以時間復雜度就是 O( T * n ) 級別的了,顯然需要優化
可以發現,因為所有 k 的總和是不超過 1e5 的,也就是說每次樹上貪心我們實際上遍歷了很多無用的點,換句話說,我們只需要每次將有用的點拿出來然后貪心就可以了
這里就要用到虛樹的虛樹的知識了,可以參考我的上一篇博客
當利用虛樹將有用的節點都拎出來后,就可以直接樹上貪心了,為了方便描述,如果一個節點屬于 k 個節點之中的話,我們就稱之為重要節點,那么貪心策略如下:對于一個節點 u 而言
套上虛樹模板再寫個dfs就好啦
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;bool vis[N];int num[N];bool cmp(int x,int y);struct virtual_tree {//原樹部分 struct{int to,next;}edge[N<<1];int head[N],cnt,deep[N],dp[N][20],limit;//樹上倍增int L[N],R[N],dfn;//dfs序 void addedge(int u,int v){edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}void dfs(int u,int fa,int dep){L[u]=++dfn;deep[u]=dep;dp[u][0]=fa;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(v!=fa)dfs(v,u,dep+1);}R[u]=dfn;}int LCA(int x,int y){if(deep[x]<deep[y])swap(x,y);for(int i=limit;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=limit;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0];}void init(int n){memset(head,-1,sizeof(head));cnt=dfn=0;limit=log2(n)+1;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}}//虛樹部分 vector<int>node[N];vector<int>ver;int Stack[N];void build(){sort(ver.begin(),ver.end(),cmp);int sz=ver.size()-1;for(int i=0;i<sz;i++)ver.push_back(LCA(ver[i],ver[i+1]));sort(ver.begin(),ver.end(),cmp);ver.erase(unique(ver.begin(),ver.end()),ver.end());int top=0;Stack[++top]=ver[0];for(int i=1;i<ver.size();i++){while(top&&R[Stack[top]]<L[ver[i]])top--;if(top)node[Stack[top]].push_back(ver[i]);Stack[++top]=ver[i];}}bool check(){for(int i=0;i<ver.size();i++)if(vis[dp[ver[i]][0]])return false;return true;}int dfs2(int u)//dp{int ans=0;for(auto v:node[u]){ans+=dfs2(v);num[u]+=num[v];}if(vis[u])//如果這個點是重要節點,需要刪去子節點中有多少個重要節點 {ans+=num[u];num[u]=1;}else if(num[u]>1)//如果這個點不是重要節點,且子節點個數大于一,那么需要刪去這個節點 {ans++; num[u]=0;}return ans;}void clear(){for(int i=0;i<ver.size();i++){vis[ver[i]]=num[ver[i]]=0;node[ver[i]].clear();}ver.clear();} }tree;bool cmp(int x,int y) {return tree.L[x]<tree.L[y]; }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n;scanf("%d",&n);tree.init(n);tree.dfs(1,0,0);int m;scanf("%d",&m);while(m--){tree.clear();int k;scanf("%d",&k);while(k--){int pos;scanf("%d",&pos);tree.ver.push_back(pos);vis[pos]=true;}if(!tree.check()){puts("-1");continue;}tree.build();printf("%d\n",tree.dfs2(tree.ver[0]));tree.clear();}return 0; }?
總結
以上是生活随笔為你收集整理的CodeForces - 613D Kingdom and its Cities(虚树+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1341E N
- 下一篇: 虚树模板