1 条题解
-
1
学不会的图论。
题目里有负权,于是这题就不能简单贪心了,考虑怎么做。
考虑图论建模。
我们用一条边表示限制关系,即“攻击某 Plant 之前先要攻击某 Plant”;点带点权。
似乎是最大权闭合子图模型?
其实并不一样,更准确的,这是最大权闭合拓扑子图。
考虑如何保证拓扑。
方法很简单,建反图跑拓扑排序,仅保留可以执行拓扑排序的点即可。
保留完这些点后建最大权闭合子图的网络流,直接跑最小割就好了。
数据范围很小,只要建图不算太离谱,怎么写都能过。
以下是核心代码。
std::vector<uint>Way[605]; int Val[605]; uint Deg[605]; voi insert(uint u,uint v){Way[u].push_back(v),Deg[v]++;} int main() { #ifdef MYEE freopen("QAQ.in","r",stdin); // freopen("QAQ.out","w",stdout); #endif uint n,m;scanf("%u%u",&n,&m); for(uint i=0,cnt=0;i<n;i++)for(uint j=0;j<m;j++,cnt++){ scanf("%d",Val+cnt);if(j)insert(cnt,cnt-1); uint p;scanf("%u",&p);while(p--){uint x,y;scanf("%u%u",&x,&y);insert(cnt,x*m+y);} } std::queue<uint>Q;for(uint i=0;i<n*m;i++)if(!Deg[i])Q.push(i); while(Q.size()){uint p=Q.front();Q.pop();for(auto s:Way[p])if(!--Deg[s])Q.push(s);} Dinic::bzr(n*m+2); uint ans=0; for(uint i=0;i<n*m;i++)if(!Deg[i]){ if(Val[i]>0)ans+=Val[i],Dinic::insert(n*m,i,Val[i]); else Dinic::insert(i,n*m+1,-Val[i]); for(auto s:Way[i])if(!Deg[s])Dinic::insert(s,i,-1); } ans-=Dinic::run(n*m,n*m+1); printf("%u\n",ans); return 0; }
- 1
信息
- ID
- 1565
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 23
- 已通过
- 9
- 上传者