• BZOJ2960:跨平面


    题面

    BZOJ

    Sol

    对该平面图的对偶图建图后就是最小树形图,建一个超级点向每个点连 (inf) 边即可

    怎么转成对偶图,怎么弄出多边形
    把边拆成两条有向边,分别挂在两个点上
    每个点的出边按角度排序
    每次选择一个没有标记过的边做 (DFS)
    (u)(v),然后 (v) 选择 ((v,u)) 顺时针转的下一条边,最后跑到原来的点,此时一定有一个多边形形成,记录编号后标记在边上即可

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
     
    IL int Input(){
        RG int x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
     
    const int maxn(100005);
    const int inf(1e9);
     
    namespace MST{
        int n, cnt, pre[maxn], vis[maxn], id[maxn], ans, inw[maxn], sum, rt;
     
        struct Edge{
            int u, v, w;
        } e[maxn];
     
        IL void Add(RG int u, RG int v, RG int w){
            e[++cnt] = (Edge){u, v, w};
        }
     
        IL int DirectedMST(){
    		for(RG int i = 1; i <= cnt; ++i) sum += e[i].w;
            ans -= (++sum);
            for(RG int i = 1; i <= n; ++i) Add(n + 1, i, sum);
            rt = ++n;
            while(true){
                RG int idx = 0;
                for(RG int i = 1; i <= n; ++i) pre[i] = id[i] = vis[i] = -1, inw[i] = inf;
                for(RG int i = 1; i <= cnt; ++i)
                    if(e[i].u != e[i].v && e[i].w < inw[e[i].v]) inw[e[i].v] = e[i].w, pre[e[i].v] = e[i].u;
                inw[rt] = 0, pre[rt] = rt;
                for(RG int i = 1; i <= n; ++i){
                    ans += inw[i];
                    if(vis[i] == -1){
                        RG int x = i;
                        while(vis[x] == -1) vis[x] = i, x = pre[x];
                        if(x != rt && vis[x] == i){
                            id[x] = ++idx;
                            for(RG int j = pre[x]; j != x; j = pre[j]) id[j] = idx;
                        }
                    }
                }
                if(!idx) break;
                for(RG int i = 1; i <= n; ++i) if(id[i] == -1) id[i] = ++idx;
                for(RG int i = 1; i <= cnt; ++i)
                    e[i].w -= inw[e[i].v], e[i].u = id[e[i].u], e[i].v = id[e[i].v];
                n = idx, rt = id[rt];
            }
            return ans;
        }
    }
     
    struct Line{
        int u, v, id, type;
        double k;
     
        IL int operator <(RG Line b) const{
            return k < b.k;
        }
    } line[maxn];
     
    struct Point{
        int x, y;
    } a[maxn];
     
    struct Edge{
        int u, v, next, type, id;
    } edge[maxn];
     
    int n, m, num, first[maxn], cnt, mat[2][maxn], vis[maxn], val[2][maxn];
     
    IL void Add(RG int u, RG int v, RG int type, RG int id){
        edge[cnt] = (Edge){u, v, first[u], type, id}, first[u] = cnt++;
    }
     
    IL int Dfs(RG int u, RG int ff){
        if(vis[u]) return ++MST::n;
        for(RG int e = first[u]; e != -1; e = edge[e].next){
            RG int v = edge[e].v, id, type;
            if(v == ff){
                e = edge[e].next;
                if(e == -1) e = first[u];
                v = edge[e].v, id = edge[e].id, type = edge[e].type;
                return mat[type][id] = Dfs(v, u);
            }
        }
        return 0;
    }
     
    int main(){
        n = Input(), m = Input();
        for(RG int i = 1; i <= n; ++i) first[i] = -1;
        for(RG int i = 1; i <= n; ++i) a[i].x = Input(), a[i].y = Input();
        for(RG int i = 1, x, y; i <= m; ++i){
            x = Input(), y = Input(), val[0][i] = Input(), val[1][i] = Input();
            line[++num] = (Line){x, y, i, 0}, line[num].k = atan2(a[y].y - a[x].y, a[y].x - a[x].x);
            line[++num] = (Line){y, x, i, 1}, line[num].k = atan2(a[x].y - a[y].y, a[x].x - a[y].x);
        }
        sort(line + 1, line + num + 1);
        for(RG int i = 1; i <= num; ++i) Add(line[i].u, line[i].v, line[i].type, line[i].id);
        for(RG int i = 0; i < cnt; ++i)
            if(!mat[edge[i].type][edge[i].id]){
                vis[edge[i].u] = 1;
                mat[edge[i].type][edge[i].id] = Dfs(edge[i].v, edge[i].u);
                vis[edge[i].u] = 0;
            }
        for(RG int i = 1; i <= m; ++i){
            if(val[0][i]) MST::Add(mat[0][i], mat[1][i], val[0][i]);
            if(val[1][i]) MST::Add(mat[1][i], mat[0][i], val[1][i]);
        }
        printf("%d
    ", MST::DirectedMST());
        return 0;
    }
    
  • 相关阅读:
    C#多线程中lock的用法
    杭州交通违规处理地点大全
    J2me c/s结构,访问数据库
    谁将成为下一个Twitter?最新最酷的创业奇思妙想
    那些相见恨晚的 JavaScript 技巧
    Adobe Dreamweaver CS5试用点滴感受
    python百炼成钢实例008输出 9*9 乘法口诀表
    python百炼成钢实例006斐波那契数列输出最后一个和整个数列,迭代
    python百炼成钢实例007复制,浅拷贝和深拷贝
    python百炼成钢实例080猴子分桃
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/9192164.html
Copyright © 2020-2023  润新知