zoukankan      html  css  js  c++  java
  • POJ3498最大流,枚举终点,企鹅,基础最大流

    题意:
          有一n个冰块,每个冰块上都有一些企鹅,所有的企鹅要跳到一个冰块上去,但是由于起跳是的后坐力原因导致每个冰块最多条mi次,最后问你所有的企鹅都跳到一个冰块上去的那块冰块可以是哪一块,输出所有肯能的终点冰块。


    思路:
          比较简单,我们可以枚举终点,首先把终点拿出来,剩下的点拆点,拆成两个,限流是最多的跳跃次数,然后起点连接每个拆了的点的左侧的点,终点就是当前枚举的点,然后最大流判断下就行了,提醒下,建图的时候注意,不要多虚拟出来一些没用的点,一开始我的第一感觉就是三重的,后来在敲的时候突然感觉两重就够了,也就是最多200个点就行,还有就是当前枚举的重点的冰块上的企鹅不用动,别的没什么,因为比较简单,我就不解释太多了,不清楚的自己画画建出来的图应该很容易懂。


    #include<queue>
    #include<stdio.h>
    #include<string.h>


    #define N_node 200 + 10
    #define N_edge 100000
    #define INF 1000000000


    using namespace std;


    typedef struct
    {
        int to ,cost ,next;
    }STAR;


    typedef struct
    {
        int x ,t;
    }DEP;


    typedef struct
    {
        double x ,y;
        int p ,c;
    }NODE;


    NODE node[N_node];
    STAR E[N_edge];
    DEP xin ,tou;
    int list[N_node] ,listt[N_node] ,tot;
    int deep[N_node] ,Ans[N_node];
    int canlink[110][110];


    void add(int a ,int b ,int c)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].next = list[a];
        list[a] = tot;


        E[++tot].to = a;
        E[tot].cost = 0;
        E[tot].next = list[b];
        list[b] = tot;
    }


    int minn(int x ,int y)
    {
        return x < y ? x : y;
    }


    bool BFS_DEEP(int s ,int t ,int n)
    {
        memset(deep ,255 ,sizeof(deep));
        xin.x = s ,xin.t = 0;
        queue<DEP>q;
        q.push(xin);
        deep[s] = 0;
        while(!q.empty())
        {
            tou = q.front();
            q.pop();
            for(int k = list[tou.x] ;k ;k = E[k].next)
            {
                xin.x = E[k].to;
                xin.t = tou.t + 1;
                if(deep[xin.x] != -1 || !E[k].cost)
                continue;
                deep[xin.x] = xin.t;
                q.push(xin);
            }
        }
        for(int i = 0 ;i <= n ;i ++)
        listt[i] = list[i];
        return deep[t] != -1;
    }


    int DFS_Flow(int s ,int t ,int flow)
    {
        if(s == t) return flow;
        int nowflow = 0;
        for(int k = listt[s] ;k ;k = E[k].next)
        {
            listt[s] = k;
            int c = E[k].cost;
            int to = E[k].to;
            if(!c || deep[to] != deep[s] + 1)
            continue;
            int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
            nowflow += tmp;
            E[k].cost -= tmp;
            E[k^1].cost += tmp;
            if(nowflow == flow) break;
        }
        if(!nowflow) deep[s] = 0;
        return nowflow;
    }


    int DINIC(int s ,int t ,int n)
    {
        int ans = 0;
        while(BFS_DEEP(s ,t ,n))
        {
            ans += DFS_Flow(s ,t ,INF);
        }
        return ans;
    }


    double Get_Dis(NODE a ,NODE b)
    {
        double x = (a.x - b.x) * (a.x - b.x);
        double y = (a.y - b.y) * (a.y - b.y);
        return x + y;
    }


    int main ()
    {
        int t ,n ,i ,j ,sump;
        double dis;
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d %lf" ,&n ,&dis);
            sump = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%lf %lf %d %d" ,&node[i].x ,&node[i].y ,&node[i].p ,&node[i].c);
                sump += node[i].p;
            }
            memset(canlink ,0 ,sizeof(canlink));
            for(i = 1 ;i <= n ;i ++)
            for(j = i + 1 ;j <= n ;j ++)
            {
                if(Get_Dis(node[i] ,node[j]) <= dis * dis)
                canlink[i][j] = canlink[j][i] = 1;
            }
            int ansid = 0;
            for(int now = 1 ;now <= n ;now ++)
            {
                memset(list ,0 ,sizeof(list));
                tot = 1;
                for(i = 1 ;i <= n ;i ++)
                {
                    if(i == now) continue;
                    add(0 ,i ,node[i].p);
                    add(i ,i + n ,node[i].c);
                }
                for(i = 1 ;i <= n ;i ++)
                for(j = i + 1 ;j <= n ;j ++)
                {
                    if(canlink[i][j])
                    {
                        if(i == now) add(j + n ,now ,INF);
                        else if(j == now) add(i + n ,now ,INF);
                        else add(i + n ,j ,INF) ,add(j + n ,i ,INF);
                    }
                }
                int flow = DINIC(0 ,now ,n + n);
                if(flow == sump - node[now].p)
                Ans[++ansid] = now;
            }
            if(!ansid) printf("-1 ");
            else
            {
                for(i = 1 ;i <= ansid ;i ++)
                if(i == ansid) printf("%d " ,Ans[i] - 1);
                else printf("%d " ,Ans[i] - 1);
            }
        }
        return 0;
    }













  • 相关阅读:
    通过写一个Demo展示C#中多种常用的集合排序方法
    【MM系列】SAP MM模块-打开前面物料账期的方法
    【FICO系列】SAP FICO模块-财务账期的打开和关闭
    【ABAP系列】SAP LSWM处理时,网络中断,出现错误
    【ABAP系列】SAP ABAP模块-ABAP动态指针写法的精髓部分
    【MM系列】SAP MM模块-MIGO收货后自动打印收货单
    【ABAP系列】SAP ABAP模块-任意report作为附件以邮件形式发送
    【ABAP系列】SAP ABAP模块-memory内存数据传输的例子
    【ABAP系列】SAP ABAP模块-查找系统出口或BADI的方法
    【MM系列】SAP MM模块-查看移动平均价的历史记录
  • 原文地址:https://www.cnblogs.com/csnd/p/12062460.html
Copyright © 2011-2022 走看看