zoukankan      html  css  js  c++  java
  • BZOJ2960 : 跨平面

    平面图求域之后增加超级根,然后建图求最小树形图即可。

    #include<cstdio>
    #include<cmath>
    #include<set>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=3010,M=10010,inf=0x7fffffff;
    int n,m,q,cnt,i,x,y,z1,z2;
    struct P{
      int x,y;
      P(){}
      P(int _x,int _y){x=_x,y=_y;}
      ll operator*(const P&b){return 1LL*x*b.y-1LL*y*b.x;}
    }a[N],b[M];
    struct E{
      int x,y,z;double o;
      E(){}
      E(int _x,int _y,int _z){x=_x,y=_y,z=_z,o=atan2(a[y].x-a[x].x,a[y].y-a[x].y);}
    }e[M];
    bool del[M];int from[M];
    namespace GetArea{
    struct cmp{bool operator()(int a,int b){return e[a].o<e[b].o;}};
    set<int,cmp>g[N];set<int,cmp>::iterator k;int i,j,q[M],t;
    void work(){
      for(i=0;i<m+m;i++)if(!del[i]){
        for(q[t=1]=j=i;;q[++t]=j=*k){
          k=g[e[j].y].find(j^1);k++;
          if(k==g[e[j].y].end())k=g[e[j].y].begin();
          if(*k==i)break;
        }
        ll s=0;
        for(j=1;j<=t;j++)s+=a[e[q[j]].x]*a[e[q[j]].y],del[q[j]]=1;
        if(s<0)continue;
        for(cnt++,j=1;j<=t;j++)from[q[j]]=cnt;
      }
    }
    }
    namespace DMST{
    int n,size,pre[N],id[N],vis[N],in[N];
    struct EDGE{
      int u,v,cost;
      EDGE(){}
      EDGE(int a,int b,int c):u(a),v(b),cost(c){}
    }E[M];
    void init(int _n){n=_n,size=0;}
    void add(int u,int v,int w){E[size++]=EDGE(u,v,w);}
    int dmst(int root){
      int u,v,cnt,ret=0,i;
      while(1){
        for(i=0;i<n;i++)in[i]=inf;
        for(i=0;i<size;i++){
          u=E[i].u,v=E[i].v;
          if(E[i].cost<in[v]&&u!=v)pre[v]=u,in[v]=E[i].cost;
        }
        for(cnt=in[root]=i=0;i<n;i++)id[i]=vis[i]=-1;
        for(i=0;i<n;i++){
          ret+=in[i],v=i;
          while(vis[v]!=i&&id[v]==-1&&v!=root)vis[v]=i,v=pre[v];
          if(v!=root&&id[v]==-1){
            for(u=pre[v];u!=v;u=pre[u])id[u]=cnt;
            id[v]=cnt++;
          }
        }
        if(!cnt)break;
        for(i=0;i<n;i++)if(id[i]==-1)id[i]=cnt++;
        for(i=0;v=E[i].v,i<size;i++){
          E[i].u=id[E[i].u],E[i].v=id[E[i].v];
          if(E[i].u!=E[i].v)E[i].cost-=in[v];     
        }
        n=cnt,root=id[root];
      }
      return ret;
    }
    void work(int _n){
      n=_n;
      int i,tot=1;
      for(i=0;i<m+m;i++)if(e[i].z)add(from[i],from[i^1],e[i].z),tot+=e[i].z;
      for(i=0;i<n-1;i++)add(n-1,i,tot);
      printf("%d",dmst(n-1)-tot);
    }
    }
    int main(){
      scanf("%d%d",&n,&m);
      for(i=1;i<=n;i++){
        scanf("%d%d",&x,&y);
        a[i]=P(x,y);
      }
      for(i=0;i<m;i++){
        scanf("%d%d%d%d",&x,&y,&z1,&z2);
        e[i<<1]=E(x,y,z1);
        e[i<<1|1]=E(y,x,z2);
      }
      for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i);
      GetArea::work();
      DMST::work(cnt+2);
      return 0;
    }
    

      

  • 相关阅读:
    C# 高级编程语言
    unity ForceMode
    UnityError 切换场景灯光变黑问题解决
    Unity Time.timeScale
    Unity 打开网页 Application.OpenURL(字符串);
    Unity www动态加载网上图片
    Unity GameObject.Find 和 transform.Find
    Unity UGUI按钮添加点击事件
    事务
    git和redis
  • 原文地址:https://www.cnblogs.com/clrs97/p/5027988.html
Copyright © 2011-2022 走看看