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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LuoguP4606 [SDOI2018]战略游戏

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LuoguP4606 [SDOI2018]战略游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LuoguP4606 [SDOI2018]戰略游戲

題目描述

題目描述
省選臨近,放飛自我的小 QQ 無心刷題,于是慫恿小 CC 和他一起頹廢,玩起了一款戰略游戲。
這款戰略游戲的地圖由 nn 個城市以及 mm 條連接這些城市的雙向道路構成,并且從任意一個城市出發總能沿著道路走到任意其他城市。
現在小 CC 已經占領了其中至少兩個城市,小 QQ 可以摧毀一個小 CC 沒占領的城市,同時摧毀所有連接這個城市的道路。只要在摧毀這個城市之后能夠找到某兩個小 CC 占領的城市 uu 和 vv,使得從 uu 出發沿著道路無論如何都不能走到 vv,那么小 QQ 就能贏下這一局游戲。
小 QQ 和小 CC 一共進行了 qq 局游戲,每一局游戲會給出小 CC 占領的城市集合 SS,你需要幫小 QQ 數出有多少個城市在他摧毀之后能夠讓他贏下這一局游戲。

Solution

題意:給定一個nnn個點mmm條邊的無向圖,QQQ組詢問,每次給出一個點集{S}\{S\}{S},詢問有多少點被刪掉之后,點集{S}\{S\}{S}會存在兩點不連通。

建廣義圓方樹。
建出圓方樹之后,讓兩個點u,vu,vu,v不連通相當于刪掉了除了u,vu,vu,v以外的某一個u?>vu->vu?>v路徑上的圓點。

設點集{S}={a1,a2,...,ak}\{S\}=\{a_1,a_2,...,a_k\}{S}={a1?,a2?,...,ak?}
點集中的點按dfsdfsdfs序排序,
令相鄰點對(包括(a1,ak)(a_1,a_k)(a1?,ak?))之間路徑的圓點數量和為ansansans
總的答案即為ans/2?k+[LCA(a1,ak)為圓點]ans/2-k+[LCA(a_1,a_k)為圓點]ans/2?k+[LCA(a1?,ak?)]

時間復雜度O(nlg?n)O(n\lg n)O(nlgn)
這題也可以用虛樹做,其實和上述方法差不多,只是實現方式不同。

#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=1e9+7; const int MAXN=200005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } vector<int> e[MAXN],E[MAXN]; int n,m,dep[MAXN],Log[MAXN],a[MAXN]; int dfn[MAXN],low[MAXN],stk[MAXN],fa[MAXN][20],dist[MAXN],bnum=0,top=0,DFN=0; int compare(int x,int y) { return dfn[x]<dfn[y]; } void add_edge(int u,int v){ /*cout<<"Edge:"<<u<<" "<<v<<endl;*/ E[u].PB(v),E[v].PB(u); } void tarjan(int x,int father) {dfn[x]=low[x]=++DFN;stk[++top]=x;for (auto v:e[x]){if (v==father) continue;if (dfn[v]) { low[x]=min(low[x],dfn[v]); continue; }tarjan(v,x);low[x]=min(low[x],low[v]);if (low[v]>=dfn[x]){int y;bnum++;add_edge(n+bnum,x);while (y=stk[top--]){add_edge(n+bnum,y);if (v==y) break;}}} } void dfs(int x,int father) { // cout<<x<<" "<<father<<endl;dfn[x]=++DFN;dep[x]=dep[father]+1;fa[x][0]=father;for (int i=1;i<=Log[dep[x]];i++) fa[x][i]=fa[fa[x][i-1]][i-1];for (auto v:E[x])if (v!=father) dist[v]=dist[x]+(v<=n),dfs(v,x); } int get_LCA(int x,int y) {if (dep[x]<dep[y]) swap(x,y);for (int i=Log[dep[x]];i>=0;i--)if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];if (x==y) return x;for (int i=Log[dep[x]];i>=0;i--)if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0]; } int getans(int x,int y) {int lca=get_LCA(x,y); // cout<<x<<":"<<dist[x]<<" "<<y<<":"<<dist[y]<<" "<<lca<<":"<<dist[lca]<<endl; // cout<<dep[x]<<" "<<dep[y]<<" "<<dep[lca]<<endl; return dist[x]+dist[y]-dist[lca]*2; } void Init() {bnum=0,top=0,DFN=0;memset(dist,0,sizeof dist);memset(dfn,0,sizeof dfn);memset(fa,0,sizeof fa);memset(low,0,sizeof low);for (int i=1;i<=n*2;i++) e[i].clear(),E[i].clear(); } int main() { // freopen("c.in","r",stdin); n=read(),m=read();int q=read();Init();for (int i=1;i<=m;i++){int u=read(),v=read();e[u].PB(v);e[v].PB(u);}tarjan(1,0);dep[0]=-1,Log[1]=0,dist[1]=0;for (int i=2;i<=n*2;i++) Log[i]=Log[i>>1]+1; DFN=0;dfs(1,0);while (q--){int k=2;a[1]=read(),a[2]=read();sort(a+1,a+k+1,compare);int ans=getans(a[1],a[k]);for (int i=1;i<k;i++) ans+=getans(a[i],a[i+1]); // cout<<"Ans:"<<ans<<endl;printf("%d\n",ans/2-k+(get_LCA(a[1],a[k])<=n));}return 0; }

總結

以上是生活随笔為你收集整理的LuoguP4606 [SDOI2018]战略游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

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