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;

}

  

你可能感兴趣的:(IE)