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;
    }













  • 相关阅读:
    LeetCode 1110. Delete Nodes And Return Forest
    LeetCode 473. Matchsticks to Square
    LeetCode 886. Possible Bipartition
    LeetCode 737. Sentence Similarity II
    LeetCode 734. Sentence Similarity
    LeetCode 491. Increasing Subsequences
    LeetCode 1020. Number of Enclaves
    LeetCode 531. Lonely Pixel I
    LeetCode 1091. Shortest Path in Binary Matrix
    LeetCode 590. N-ary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/csnd/p/12062461.html
Copyright © 2011-2022 走看看