Firing

http://poj.org/problem?id=2987

知识点:1.最大权闭合子图

    2.关于统计留下多少个人:dfs查询每条边是否满流,满流就留下来了(灵活运用跑完网络流留下来的残留图)

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define int long long
using namespace std;
int n,m;
int f[5010];
struct edge
{
    int to;
    int nxt;
    int len;
}e[60010 << 1];
int head[60010],cnt = 1;
void add(int x,int y,int len)
{
    e[++cnt].nxt = head[x];
    e[cnt].to = y;
    e[cnt].len = len;
    head[x] = cnt;
} 
int S = 5100,T = 5120;    
int psum = 0;
int deep[6010];
queue <int> q;
int bfs()
{
    memset(deep,0,sizeof(deep));
    deep[S] = 1;
    q.push(S);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i = head[u];i;i  = e[i].nxt)
        {
            int np = e[i].to;
            if(deep[np] == 0 && e[i].len)
            {
                deep[np] = deep[u] + 1;
                q.push(np);
            }
        }
    }

    if(deep[T] == 0)return 0;
    else return 1;
}
int dfs(int t,int minn)
{
    if(t == T)
    return minn;
    int tans = 0;
    for(int i = head[t];i;i = e[i].nxt)
    {
        if(e[i].len)
        {
            int np = e[i].to;
            if(deep[np] == deep[t] + 1)
            {
                int he1 = dfs(np,min(e[i].len,minn));
                if(he1)
                {
                    tans += he1;
                    minn -= he1;
                    e[i].len -= he1;
                    e[i^1].len += he1;
                    if(minn == 0)break;
                }
            }
        }
    }
    return tans;
}
int vis[100010];
int dfs(int u){
    int ans = 1;
    vis[u] = 1;
    for(int i = head[u];i;i = e[i].nxt)
    {
    int v = e[i].to;
    if(e[i].len > 0&& !vis[v])
    {
        ans+=dfs(v);
    }
    }
    return ans;
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i = 1;i <= n;i++)
        scanf("%lld",&f[i]);
    int x,y;
    while(m--)
    {
        scanf("%lld%lld",&x,&y);
        add(x,y,2147483640),add(y,x,0);
    }
    for(int i = 1;i <= n;i++)
    {
        if(f[i] > 0)psum += f[i];
        if(f[i] > 0)add(S,i,f[i]),add(i,S,0);
        else if(f[i] < 0)add(i,T,-f[i]),add(T,i,0);
    }
    int ret = 0;
    while(bfs())
    {
        ret += dfs(S,999999999); 
        
    }
    printf("%lld %lld",dfs(S) - 1,psum - ret);
    return 0;
}

 

posted @ 2020-09-16 13:37  ywwywwyww  阅读(162)  评论(0编辑  收藏  举报