zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph (上下界网络流)

    正解:

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN=10010;//点数的最大值
    const int MAXM=400010;//边数的最大值
    #define captype int
    
    struct SAP_MaxFlow{
        struct EDGE{
            int to,next;
            captype cap;
        }edg[MAXM];
        int eid,head[MAXN];
        int gap[MAXN];
        int dis[MAXN];
        int cur[MAXN];
        int pre[MAXN];
    
        void init(){
            eid=0;
            memset(head,-1,sizeof(head));
        }
        void AddEdge(int u,int v,captype c,captype rc=0){
            edg[eid].to=v; edg[eid].next=head[u];
            edg[eid].cap=c;  head[u]=eid++;
            edg[eid].to=u; edg[eid].next=head[v];
            edg[eid].cap=rc; head[v]=eid++;
        }
        captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
            memset(gap,0,sizeof(gap));
            memset(dis,0,sizeof(dis));
            memcpy(cur,head,sizeof(head));
            pre[sNode] = -1;
            gap[0]=n;
            captype ans=0;
            int u=sNode;
            while(dis[sNode]<n){
                if(u==eNode){
                    captype Min=INF ;
                    int inser;
                    for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to])
                    if(Min>edg[i].cap){
                        Min=edg[i].cap;
                        inser=i;
                    }
                    for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
                        edg[i].cap-=Min;
                        edg[i^1].cap+=Min;
                    }
                    ans+=Min;
                    u=edg[inser^1].to;
                    continue;
                }
                bool flag = false;
                int v;
                for(int i=cur[u]; i!=-1; i=edg[i].next){
                    v=edg[i].to;
                    if(edg[i].cap>0 && dis[u]==dis[v]+1){
                        flag=true;
                        cur[u]=pre[v]=i;
                        break;
                    }
                }
                if(flag){
                    u=v;
                    continue;
                }
                int Mind= n;
                for(int i=head[u]; i!=-1; i=edg[i].next)
                if(edg[i].cap>0 && Mind>dis[edg[i].to]){
                    Mind=dis[edg[i].to];
                    cur[u]=i;
                }
                gap[dis[u]]--;
                if(gap[dis[u]]==0) return ans;
                dis[u]=Mind+1;
                gap[dis[u]]++;
                if(u!=sNode) u=edg[pre[u]^1].to;  //退一条边
            }
            return ans;
        }
    }F;
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int cas = 1;
        int N,M,K,u,v;
        while(scanf("%d %d %d",&N,&M,&K)==3){
            int L,R; scanf("%d %d",&L,&R);
            F.init();
            int s= 0,t = N+M+1;
            int S = N+M+2,T = N+M+3;
            F.AddEdge(t,s,INF);
            F.AddEdge(s,T,L*N);
            F.AddEdge(S,t,L*M);
            for(int i=1;i<=N;++i) F.AddEdge(s,i,R-L), F.AddEdge(S,i,L);
            for(int i=1;i<=M;++i) F.AddEdge(i+N,t,R-L),F.AddEdge(i+N,T,L);
            while(K--){
                scanf("%d %d",&u,&v);
                F.AddEdge(u,v+N,1);
            }
            int f = F.maxFlow_sap(S,T,N+M+4);
    
    
            printf("Case %d: ",cas++);
            if(f==(N+M)*L) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    
    

    假算法
    分析:贪心地删边后检查每个点的度即可,居然能过?

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e4+5;
    struct Edge{
        int u,v,next;
    }edges[MAXN<<2];
    int head[MAXN],tot;
    int deg[MAXN];
    
    void init()
    {
        memset(head,-1,sizeof(head));
        tot =0 ;
        memset(deg,0,sizeof(deg));
    }
    
    void AddEdge(int u,int v)
    {
        edges[tot] = (Edge){u,v,head[u]};
        head[u] = tot++;
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int cas = 1;
        int N,M,K,u,v;
        while(scanf("%d %d %d",&N,&M,&K)==3){
            init();
            memset(deg,0,sizeof(deg));
            int L,R; scanf("%d %d",&L, &R);
    
            for(int i=1;i<=K;++i){
                scanf("%d %d",&u,&v);
                v+=N;
                AddEdge(u,v);
                deg[u]++;  deg[v]++;
            }
    
            for(int e=0;e<tot;++e){
                u = edges[e].u, v =edges[e].v;
                if(deg[u]>R || deg[v]>R){
                    deg[u]--;
                    deg[v]--;
                }
            }
    
            bool flag = true;
    
            for(int i=1;i<=N+M;++i){
                if(deg[i]<L || deg[i]>R){
                    flag = false;
                    break;
                }
            }
            printf("Case %d: ",cas++);
            if(flag) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    
    
    为了更好的明天
  • 相关阅读:
    hdu 3790 最短路径问题
    hdu 2112 HDU Today
    最短路问题 以hdu1874为例
    hdu 1690 Bus System Floyd
    hdu 2066 一个人的旅行
    hdu 2680 Choose the best route
    hdu 1596 find the safest road
    hdu 1869 六度分离
    hdu 3339 In Action
    序列化和反序列化
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9610142.html
Copyright © 2011-2022 走看看