1277. Cops and Thieves 夜

http://acm.timus.ru/problem.aspx?space=1&num=1277

拆点建图  dinic 加一点小优化

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;

const int INF=0x3f3f3f3f;
const int N=205;
const int M=100005;
int head[N],I;
struct node
{
    int j,next;
    int flow;
}edge[M];
int L[N];//距离标号
int st,nd;//
void add(int i,int j,int flow)//建图
{
    edge[I].j=j;
    edge[I].flow=flow;
    edge[I].next=head[i];
    head[i]=I++;
}
bool bfs(int x1,int x2)//从汇点向源点搜索并标号 如果搜不到返回 false
{                       //和从源点向汇点搜索并标号相比 在dfs的时候会节省一定的时间
    memset(L,-1,sizeof(L));
    queue<int>qt;
    qt.push(x1);
    L[x1]=0;
    while(!qt.empty())
    {
        int x=qt.front();
        qt.pop();
        for(int t=head[x];t!=-1;t=edge[t].next)
        {
            int j=edge[t].j;
            if(edge[t^1].flow>0&&L[j]==-1)//注意这里的边是 edge[t^1].flow 因为我们是反向搜索
            {
                L[j]=L[x]+1;
                qt.push(j);
            }
        }
    }
    if(L[x2]==-1)
    return false;
    return true;
}
int dfs(int x,int sum)
{
    if(x==nd)
    return sum;
    int tmp=sum;
    for(int t=head[x];t!=-1;t=edge[t].next)
    {
        int j=edge[t].j;
        if(edge[t].flow>0&&L[x]==L[j]+1)
        {
            int w=dfs(j,min(tmp,edge[t].flow));
            edge[t].flow-=w;
            edge[t^1].flow+=w;
            tmp-=w;
            if(tmp==0)
            break;
        }
    }
    return (sum-tmp);
}
void init(int n,int m,int s,int f)
{
    for(int i=1;i<=n;++i)
    {
        int k;
        cin>>k;
        if(i==s||i==f)
        continue;
        add(i,i+n,k);
        add(i+n,i,k);
    }
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        if(l==s&&r==f)
        {add(l,r,INF);add(r,l,0);continue;}
        if(r==s&&l==f)
        {add(r,l,INF);add(l,r,0);continue;}
        if(l==s)
        {add(l,r,INF);add(r,l,0);}
        else
        {add(l+n,r,INF);add(r,l+n,0);}
        if(r==s)
        {add(r,l,INF);add(l,r,0);}
        else
        {add(r+n,l,INF);add(l,r+n,0);}
    }
}
int main()
{
    //freopen("data.in","r",stdin);
    int K;
    while(scanf("%d",&K)!=EOF)
    {
        memset(head,-1,sizeof(head));
        I=0;
        int n,m,s,f;
        cin>>n>>m>>s>>f;
        st=s;//初始化源点和汇点
        nd=f;
        init(n,m,s,f);//建图
        int ans=0;//最大流
        while(bfs(nd,st))//从汇点向源点bfs
        {
            int k;
            while((k=dfs(st,INF)))
            {ans+=k;if(ans>K) break;}
            if(ans>K)//优化在这里 如果ans大于K了以后 就没有必要再搜了
            break;//因为答案一定是"NO"了 而且K的上界是10000 所以会很快
        }
        if(ans<=K)
        cout<<"YES"<<endl;
        else
        cout<<"NO"<<endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/liulangye/p/2877559.html