日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 613D Kingdom and its Cities(虚树+贪心)

發布時間:2024/4/11 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(虚树+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。