zoukankan      html  css  js  c++  java
  • 2018.12.25-dtoj-4086-针老师(truth) || dtoj-3657: 排列(permutation)

    题目描述:

    为了证明自己是 OI 界最针的人,针老师打算向全 LOJ 群最针的 wxh 发起挑战。针老师偷偷潜入 wxh 所在地的电力设施,打算一举剿灭 wxh。供电的网络是由 n 个节点组成的 DAG,每个节点有一定的 能量 (能量可能为负)。针老师仔细研修后发现,为了打败 wxh,他必须选择一个该 DAG 的拓扑序,然后 将拓扑序上连续一段的能量节点摧毁。为了制定合理的作战计划,针老师邀请你来计算最大能摧毁的能量之和。 

    算法标签:网络流

    思路:

    怎么想到网络流啊天啊神仙!

    解释一下建图,拓扑序相当于得到条件a连向b,说明a在序列中必然在b之前。于是我们把序列分成选中序列,选中序列前,及选中序列后三个部分。将每一个权值为正的数与s和t,分别连一条边,边权为点权,表示把这个点从中间移出,放到序列前或后。对于点权为负的点,把自己与s和t相连两个点连接,边权为自己点权的相反数,割掉表示把他放进中间序列。然后对于每一个限制条件,如a在b前,连接a到b,及a+n到b+n,边权是inf

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=10e3+5,M=8e3+5,inf=1e9;
    int n,m,head[N],ne[M],to[M],cnt=1,v[M],s,t,d[N],ans;queue<int> q;
    il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;}
    il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;v[cnt]=z;}
    il void add(int x,int y,int z){insert(x,y,z);insert(y,x,0);}
    il bool bfs(){
        for(int i=1;i<=t;i++)d[i]=-1;q.push(s);d[s]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=ne[i]){
                if(d[to[i]]!=-1||(!v[i]))continue;
                d[to[i]]=d[x]+1;q.push(to[i]);
            }
        }
        return d[t]!=-1;
    }
    il int dfs(int x,int f){
        if(x==t)return f;int used=0,w;
        for(int i=head[x];i;i=ne[i]){
            if(d[to[i]]!=d[x]+1||(!v[i]))continue;
            w=min(v[i],f-used);w=dfs(to[i],w);
            used+=w;v[i]-=w;v[i^1]+=w;if(used==f)return used;
        }
        if(!used)d[x]=-1;return used;
    }
    il int dinic(){int res=0;while(bfs())res+=dfs(s,inf);return res;}
    int main()
    {
        n=read();m=read();s=0;t=n<<1|1;
        for(int i=1;i<=n;i++){
            int x=read();
            if(x>0)add(s,i,x),add(i+n,t,x),ans+=x;
            else add(i,i+n,-x);
        }
        for(int i=1;i<=m;i++){
            int x=read(),y=read();add(x,y,inf);add(x+n,y+n,inf);
        }
        printf("%d
    ",ans-dinic());
        return 0;
    }
    View Code
  • 相关阅读:
    第k短路
    Codeforces Round #608 (Div. 2)
    Codeforces Round #606 E(无向图求pair(x,y)x到y的任意路径一定经过定点a和b的数量)
    Codeforces Round #603 (Div. 2)E
    题解报告:hdu 2717 Catch That Cow(bfs)
    题解报告:poj 3669 Meteor Shower(bfs)
    题解报告:poj 1321 棋盘问题(dfs)
    题解报告:hdu 1312 Red and Black(简单dfs)
    题解报告:poj 1426 Find The Multiple(bfs、dfs)
    hdu 4704 Sum(扩展欧拉定理)
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10176436.html
Copyright © 2011-2022 走看看