time limit: 30 sec memory limit: 512 mb
submit: 12 solved: 9
[submit][status][discuss]
省選臨近,放飛自我的小q無心刷題,於是慫恿小c和他一起頹廢,玩起了一款戰略遊戲。
這款戰略遊戲的地圖由n個城市以及m條連線這些城市的雙向道路構成,並且從任意乙個城市出發總能沿著道路走到
任意其他城市。現在小c已經占領了其中至少兩個城市,小q可以摧毀乙個小c沒占領的城市,同時摧毀所有連線這
個城市的道路。只要在摧毀這個城市之後能夠找到某兩個小c占領的城市u和v,使得從u出發沿著道路無論如何都不
能走到v,那麼小q就能贏下這一局遊戲。
小q和小c一共進行了q局遊戲,每一局遊戲會給出小c占領的城市集合s
你需要幫小q數出有多少個城市在他摧毀之後能夠讓他贏下這一局遊戲。
第一行包含乙個正整數t,表示測試資料的組數,
對於每組測試資料,
第一行是兩個整數n和m,表示地圖的城市數和道路數,
接下來m行,每行包含兩個整數u和v~(1<=u表示第u個城市和第v個城市之間有一條道路,同一對城市之間可能有多條道路連線,
第m+1是乙個整數q,表示遊戲的局數,
接下來q行,每行先給出乙個整數|s|(2<=|s|<=n)
表示小c占領的城市數量,然後給出|s|個整數s1,s2,...s|s|,(1<=s11<= t<= 10,
2<= n<= 10^5 且 n-1<= m<= 2*10^5,
1<= q<= 10^5,
對於每組測試資料,有sigma|s|<= 2*10^5
對於每一局遊戲,輸出一行,包含乙個整數,表示這一局遊戲中有多少個城市在小q摧毀之後能夠讓他贏下這一局遊戲。
7 61 2
1 32 4
2 53 6
3 73
2 1 2
3 2 3 4
4 4 5 6 7
6 61 2
1 32 3
1 42 5
3 64
3 1 2 3
3 1 2 6
3 1 5 6
3 4 5 601
3012
3考場上想出來發現是個圓方樹。。。但是以前沒寫過怎麼辦啊qwq
不管了,硬鋼吧23333
(然後最後就神奇的鋼出來了)
#include#include#include#include#include#include#include#include#include#include#define ll long long#define pb push_back
#define mid (l+r>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
using namespace std;
using namespace std::tr1;
const int maxn=400005;
vectorg[maxn];
unordered_mapmmp[maxn];
int t,n,m,num,hd[maxn],to[maxn*2],ne[maxn*2];
int dfn[maxn],low[maxn],dc,cnt,rp[maxn],dy[maxn],dep[maxn];
int siz[maxn],son[maxn],cl[maxn],f[maxn],l,q,now[maxn],k,ans;
int lim[maxn*4],sum[maxn*4],le,ri,w,tag[maxn*4];
struct lines;
stacks;
inline int read()
void wt(int x) if(x>=10) wt(x/10); putchar(x%10+'0');}
inline void add(int x,int y)
inline void add(int x,int y)
inline void init()
void dfs(int x,int fa);
if(!dfn[to[i]])}}
else if(dfn[to[i]]=0;i--)}
void build(int o,int l,int r)
build(lc,l,mid),build(rc,mid+1,r);
lim[o]=lim[lc]+lim[rc];}
inline void work1(int o)
inline void work2(int o)
inline void pushdown(int o)
else if(tag[o])
tag[o]=0;}
inline void maintain(int o)
void update1(int o,int l,int r)
pushdown(o);
if(le<=mid) update1(lc,l,mid);
if(ri>mid) update1(rc,mid+1,r);
maintain(o);}
void update2(int o,int l,int r)
pushdown(o);
if(le<=mid) update2(lc,l,mid);
if(ri>mid) update2(rc,mid+1,r);
maintain(o);}
inline int lca(int x,int y)
return dep[x]>dep[y]?y:x;}
inline void paint(int x)}
inline void rev(int x) }
inline void solve()
*/memset(dfn,0,sizeof(dfn)),dc=0;
rp[1]=1,dfs1(1,0),dfs2(1,1);
build(1,1,cnt);
q=read();
while(q--)
wt(ans-rp[f[l]]-k),puts("");
for(int i=1;i<=k;i++) rev(now[i]);
}} int main()
for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,-1);
solve();
}return 0;
}
SDOI2018 戰略遊戲
給定一張 n 個點 m 條邊的無向聯通圖,共有 q 次操作,每次操作選擇一些點作為關鍵點,詢問有多少個點滿足刪去該點及與其相鄰的邊後,至少有兩個關鍵點不能互相到達。n,q leq 10 5,m leq 2 cdot 10 5,sum s leq 2 cdot 10 5 還是挺簡單的。就是圓方樹 虛樹...
SDOI2018 戰略遊戲
題目 圓方樹其實並沒有那麼難 圓方樹的構建比較簡單,就是乙個tarjan把點雙跑出來,對於每乙個點雙我們多建乙個方點,把原圖中的點稱為圓點,將點雙內所有圓點向方點連邊,之後我們就得到了原圖的圓方樹 關於圓方樹的性質,zyb大爺在他的題解裡寫了很多,這裡就不再抄一遍了 至於這道題,就是把圓點拿出來建棵...
解題 SDOI2018 戰略遊戲
題面 先圓方樹然後建虛樹,答案就是虛樹大小。虛樹沒必要建出來,把原來的點的點權設為1,直接dfs序排序後相鄰點求距離加上首尾兩個點的距離,最後除以二 畫一下可以發現是正反算了兩遍 注意還要去掉詢問點和補上首尾兩個點的lca 1 include2 include3 include4 include5 ...