題意:一棵樹上給定點集,求到根的最小割。
每次詢問只和給定的點集以及它們的lca有關係,那麼把這些點拿出來建立一棵樹。再進行樹dp。具體操作把所有詢問點按照dfn排序,再用乙個棧進行維護建樹。彈棧的時候並不是每個點都和棧中第二個元素連邊,有可能最後乙個彈棧點和新的lca連邊。dp轉移時需要查詢樹鏈的最小邊,這裡用倍增做。
#include#define cmin(a,b) (a>b?a=b:a)view codeusing
namespace
std;
typedef
long
long
ll;const
int n=5e5+10
;const
int m=2.5e5+10
;int head[n],ver[2*m],edge[2*m],nex[2*m],tot=1
;inline
void add(int x,int y,int
z) int d[n],f[n][25],min[n][25
],dfn[n],num,_t,n;
void dfs(int x)
dfs(y);
}}int lca(int x,int
y) int minedge(int x,int y)
cmin(res,min[x][
0]);cmin(res,min[y][0
]);
return
res;
}bool cmp(int x,int y)
intstk[n],top,fa[n],a[n],in_deg[n],cntq;
void build()
if(dfn[stk[top]]>dfn[lca])fa[stk[top--]]=lca,++in_deg[lca];
if(stk[top]!=lca)stk[++top]=lca;
stk[++top]=a[i];
}while(top>1)}
ll dp[n];
int isq[n],clear[n],cnt;//
isq:詢問點,clear:等待清空
ll solve()
ll ans=dp[1
];
for(int i=0;i0;//
清空dp陣列
for(int i=0;i0;//
清空詢問點標記
return
ans;
}int
main()
_t=log(n+0.5)/log(2);//
init
d[1]=1;//
init
dfs(1
); scanf("%d
",&m);
while(m--)
return0;
}
虛樹 P2495 SDOI2011 消耗戰
好久沒有學習新的知識了。今天我學習了一下虛樹。虛樹就是乙個不存在的樹。用來簡化問題。它只包括一些關鍵點和他的lca 我們來看看上面這一道題 給出一棵樹,含有邊權。每次詢問給出k個點,然後詢問每個點與根斷開的最小代價。因為資料的關係肯定沒法直接dp過去的。首先我們可以發現可以與根到其他點的路徑沒有關係...
P2495 SDOI2011 消耗戰 虛樹
這是我做的第一道虛樹題啊,趕腳不錯.其實虛樹也沒什麼奇怪的,就是每棵樹給你一些點,讓你多次查詢,但是我不想每次都o n 所以我們每次針對給的點建一棵虛樹,只包含這些點和lca,然後在這棵虛樹上進行樹形dp,維護每個點的最小連邊權值,這樣的複雜度就會降低不少.這裡我寫了兩種寫法 其實都是抄的 一種是正...
SDOI2011 消耗戰 虛樹
有m次詢問,又有詢問的總的點數之和是小於等於5e5的,所以,其實就是乙個虛樹的模板了,直接用棧維護乙個虛樹即可。期間寫的時候出現了一點問題 初始化的時候,不只是要初始那些輸入的k個結點,還有k個結點的lca的衍生結點也是需要初始化的,所以初始化不到位會mle和tle的,這裡不要忘。include i...