• POJ2391(网络流)


    题意:F个地区。已知各个地区之间的行走时间。每个地区I有两个属性:

    这个地区当前牛的个数,下雨的时候这个地区实际能够容纳牛的个数。

    问至少需要多少时间,使所有的牛在下雨的时候都能够被容纳。

    构图:先Floyd求所有点对之间最短路。二分最短时间,源向I连容量为初始牛数的边,I’向汇连容量为所能容纳牛数的边,I向I’连容量无穷大的边,若I,J能够在mid时间内到达,则连无穷大的边,用最大流判可行性。

    注意几点:

    1.点之间的距离非常大,鄙人宏定义1500000005000,同时注意long long的使用;

    2.无向图;

    3.自己可以流向自己;

    4.拆点:1流向2,2流向3并不意味着1能流向3。

    View Code
    /*Source Code
    Problem: 2391  User: HEU_daoguang
    Memory: 3132K  Time: 375MS
    Language: G++  Result: Accepted
    Source Code*/
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int n,m;
    #define infx 1500000005000
    #define inf 20000000
    #define V 3000
    #define E 200000
    struct Node{
        int s,t;
    }point[V];
    long long map[V][V];
    
    int cnt;
    int dist[V];
    int head[V];
    int que[V];
    int sta[V];
    struct Edge
    {
        int u,v,c,next;
    }edge[4*E];
    
    void init(){
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int c){
        edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
        edge[cnt].next=head[u];head[u]=cnt++;
        edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
        edge[cnt].next=head[v];head[v]=cnt++;
    }
    
    int dinic(int s,int t){
        int ans=0;
        while(true){
            int left,right,u,v;
            memset(dist,-1,sizeof(dist));
            left=right=0;
            que[right++]=s;
            dist[s]=0;
    
            while(left<right){
                u=que[left++];
                for(int k=head[u];k!=-1;k=edge[k].next){
                    u=edge[k].u;
                    v=edge[k].v;
                    if(edge[k].c > 0 && dist[v]==-1){
                        dist[v]=dist[u]+1;
                        que[right++]=v;
                        if(v==t){
                            left=right;
                            break;
                        }
                    }
                }
            }
    
            if(dist[t]==-1) break;
    
            int top=0;
            int now=s;
    
            while(true){
                if(now!=t){
                    int k;
                    for(k=head[now];k!=-1;k=edge[k].next){
                        if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break;
                    }
                    if(k!=-1){
                        sta[top++]=k;
                        now=edge[k].v;
                    }
                    else{
                        if(top==0) break;
                        dist[edge[sta[--top]].v]=-1;
                        now=edge[sta[top]].u;
                    }
                }
                else{
                    int flow=inf,ebreak;
                    for(int i=0;i<top;i++){
                        if(flow>edge[sta[i]].c){
                            flow=edge[sta[i]].c;
                            ebreak=i;
                        }
                    }
                    ans+=flow;
                    for(int i=0;i<top;i++){
                        edge[sta[i]].c-=flow;
                        edge[sta[i]^1].c+=flow;
                    }
                    now=edge[sta[ebreak]].u;
                    top=ebreak;
                }
            }
        }
        return ans;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int a,b,c,sum;
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    if(i==j) map[i][j]=0;
                    else map[i][j]=infx;
                }
            sum=0;
            for(int i=1;i<=n;i++){
                scanf("%d%d",&point[i].s,&point[i].t);
                sum+=point[i].s;
            }
            while(m--){
                scanf("%d%d%d",&a,&b,&c);
                if(c<map[a][b]) map[a][b]=map[b][a]=c;
            }
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                            map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
            long long l=-1,r=infx,mid;
            int flag=0;
            while(l<r){
                mid=(l+r)/2;
                init();
                for(int i=1;i<=n;i++){
                    addedge(0,i,point[i].s);
                    addedge(i+n,2*n+1,point[i].t);
                }
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        if(map[i][j]<=mid)
                            addedge(i,j+n,inf);
                if(dinic(0,2*n+1)==sum) r=mid,flag=1;
                else l=mid+1;
            }
            if(flag) printf("%lld\n",r);
            else printf("-1\n");
        }
        return 0;
    }
  • 相关阅读:
    java File获取字节流
    mybatis返回自增主键问题踩坑
    电脑右键没有新建选项解决
    mysql 索引
    高并发-原子性-AtomicInteger
    Cannot find the declaration of element 'ehcache'.
    CSRF拦截
    java责任链模式
    java实现一个简单的计数器
    Java并发编程
  • 原文地址:https://www.cnblogs.com/markliu/p/2512094.html
Copyright © 2020-2023  润新知