zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    LIN总线学习-总线逻辑
    使用万用表测量CAN总线电压及实际电压与逻辑电瓶关系
    汽车网络和控制单元的安全威胁研究
    [CANopen] SDO的命令字
    新起点,新开始
    Git Commands
    Obsessive String
    The E-pang Palace
    最长递增子序列(LIS)
    Valid Sets
  • 原文地址:https://www.cnblogs.com/liulangye/p/2877559.html
Copyright © 2011-2022 走看看