BZOJ2286: [Sdoi2011]消耗战
题解:首先构造虚数 然后树DP即可
/************************************************************** Problem: 2286 User: c20161007 Language: C++ Result: Accepted Time:10752 ms Memory:94812 kb ****************************************************************/ #include <bits/stdc++.h> const int MAXN=3e5+10; #define ll long long #define pii pair<int,int> using namespace std; const int inf=1e9+10; vector<pii>vec[MAXN]; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int n; int f[MAXN][21];ll minn[MAXN][21]; int dep[MAXN],cnt,p[MAXN]; int st[MAXN];int tot; vector<int>vv; ll ans[MAXN];bool vis[MAXN]; void dfs(int v,int pre,int deep){ dep[v]=deep+1;p[v]=++cnt;f[v][0]=pre; for(int i=0;i<vec[v].size();i++){ int u=vec[v][i].first; if(u!=pre){ minn[u][0]=vec[v][i].second; dfs(u,v,deep+1); } } } void dfs1(int v){ for(int i=1;i<=20;i++)f[v][i]=f[f[v][i-1]][i-1],minn[v][i]=min(minn[v][i-1],minn[f[v][i-1]][i-1]); for(int i=0;i<vec[v].size();i++){ if(vec[v][i].first!=f[v][0])dfs1(vec[v][i].first); } } int Lca(int u,int v){ if(dep[u]<dep[v])swap(u,v); int tmp=dep[u]-dep[v]; for(int i=0;i<=20;i++)if(tmp&(1<<i)){u=f[u][i];} if(u==v){return u;} for(int i=20;i>=0;i--){ if(f[u][i]!=f[v][i]){ v=f[v][i];u=f[u][i]; } } return f[v][0]; } void built(int x){ vv.push_back(x); if(!tot){st[++tot]=x;return ;} int lca=Lca(x,st[tot]); // cout<<x<<"====="<<st[tot]<<" "<<lca<<endl; while(tot>1&&dep[lca]<dep[st[tot-1]]){ vec[st[tot-1]].push_back(make_pair(st[tot],0)); vec[st[tot]].push_back(make_pair(st[tot-1],0)); tot--; } if(dep[lca]<dep[st[tot]]){ vv.push_back(lca); vec[st[tot]].push_back(make_pair(lca,0)); vec[lca].push_back(make_pair(st[tot],0)); tot--; // st[++tot]=lca; } if(!tot||dep[lca]>dep[st[tot]])st[++tot]=lca; st[++tot]=x; } ll dist(int u,int v){ if(v==0)return inf; ll res=inf; for(int i=20;i>=0;i--){ if(dep[f[u][i]]>dep[v]){ res=min(res,minn[u][i]); u=f[u][i]; } } res=min(res,minn[u][0]); return res; } void slove(int v,int pre){ // cout<<v<<" "<<pre<<endl; for(int i=0;i<vec[v].size();i++){ int u=vec[v][i].first; if(u!=pre){ slove(u,v); if(vis[u])ans[v]+=dist(u,v); else ans[v]+=min(dist(u,v),ans[u]); } } // cout<<v<<" "<<ans[v]<<" ::::"<<endl; } bool cmp(int aa,int bb){return p[aa]<p[bb];} vector<int>V; int main(){ n=read();int u,v,vul; for(int i=1;i<n;i++)u=read(),v=read(),vul=read(),vec[u].push_back(make_pair(v,vul)),vec[v].push_back(make_pair(u,vul)); int q;q=read();int k,last;dfs(1,0,0);dfs1(1); for(int i=1;i<=n;i++)vec[i].clear(); for(int i=1;i<=q;i++){ k=read();tot=0; // V.push_back(1); for(int j=1;j<=k;j++)u=read(),V.push_back(u),vis[u]=1; sort(V.begin(),V.end(),cmp); for(int j=0;j<V.size();j++)built(V[j]); while(tot>1){vec[st[tot]].push_back(make_pair(st[tot-1],0)),vec[st[tot-1]].push_back(make_pair(st[tot],0));tot--;} //vv.push_back() if(st[1]!=1){vec[1].push_back(make_pair(st[1],0));vec[st[1]].push_back(make_pair(1,0));} // else last=1; // cout<<last<<endl; slove(1,0); printf("%lld\n",ans[1]); if(st[1]!=1)vec[1].clear(),ans[1]=0; for(int j=0;j<vv.size();j++)vec[vv[j]].clear(),ans[vv[j]]=0,vis[vv[j]]=0; V.clear();vv.clear(); } return 0; }
2286: [Sdoi2011]消耗战
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5381 Solved: 2041
[Submit][Status][Discuss]
Description
在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达。现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望。已知在其他k个岛屿上有丰富能源,为了防止敌军获取能源,我军的任务是炸毁一些桥梁,使得敌军不能到达任何能源丰富的岛屿。由于不同桥梁的材质和结构不同,所以炸毁不同的桥梁有不同的代价,我军希望在满足目标的同时使得总代价最小。
侦查部门还发现,敌军有一台神秘机器。即使我军切断所有能源之后,他们也可以用那台机器。机器产生的效果不仅仅会修复所有我军炸毁的桥梁,而且会重新随机资源分布(但可以保证的是,资源不会分布到1号岛屿上)。不过侦查部门还发现了这台机器只能够使用m次,所以我们只需要把每次任务完成即可。
Input
第一行一个整数n,代表岛屿数量。
接下来n-1行,每行三个整数u,v,w,代表u号岛屿和v号岛屿由一条代价为c的桥梁直接相连,保证1<=u,v<=n且1<=c<=100000。
第n+1行,一个整数m,代表敌方机器能使用的次数。
接下来m行,每行一个整数ki,代表第i次后,有ki个岛屿资源丰富,接下来k个整数h1,h2,…hk,表示资源丰富岛屿的编号。
Output
输出有m行,分别代表每次任务的最小代价。
Sample Input
10
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
3
2 10 6
4 5 7 8 3
3 9 4 6
1 5 13
1 9 6
2 1 19
2 4 8
2 3 91
5 6 8
7 5 4
7 8 31
10 7 9
3
2 10 6
4 5 7 8 3
3 9 4 6
Sample Output
12
32
22
32
22
HINT
对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1