1 条题解

  • 1
    @ 2022-11-15 9:22:09

    学不会的图论。

    题目里有负权,于是这题就不能简单贪心了,考虑怎么做。

    考虑图论建模。

    我们用一条边表示限制关系,即“攻击某 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
    上传者