zoukankan      html  css  js  c++  java
  • HDU5518 : John's Fences

    求出平面图的对偶图,那么需要选择一些环,使得这些环可以异或出所有环。

    对于两个不同的区域,需要用一个代价最小的环把它们区分开,这对应最小割。

    那么求出对偶图的最小割树,所有树边之和就是把所有区域都区分开的最小代价。

    #include<cstdio>
    #include<cmath>
    #include<set>
    #include<algorithm>
    #include<map>
    using namespace std;
    typedef pair<int,int>PI;
    typedef long long ll;
    const int N=1010,M=2010,inf=~0U>>2;
    int Case,cas,n,m,cnt,i,x,y,z;map<PI,int>T;
    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];
    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 GH{
    struct E{int t,f;E*nxt,*pair;}*g[N],*d[N],pool[10000],*cur;
    int n,m,i,e[M][3],S,T,h[N],gap[N],maxflow,vis[N],a[N],b[N],ans;
    void init(int _n){n=_n;m=ans=0;}
    inline void newedge(int x,int y,int z){e[++m][0]=x;e[m][1]=y;e[m][2]=z;}
    inline void add(int s,int t,int f){
      E*p=cur++;p->t=t;p->f=f;p->nxt=g[s];g[s]=p;
      p=cur++;p->t=s;p->f=0;p->nxt=g[t];g[t]=p;
      g[s]->pair=g[t];g[t]->pair=g[s];
    }
    inline int min(int a,int b){return a<b?a:b;}
    int sap(int v,int flow){
      if(v==T)return flow;
      int rec=0;
      for(E*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
        int ret=sap(p->t,min(flow-rec,p->f));
        p->f-=ret;p->pair->f+=ret;d[v]=p;
        if((rec+=ret)==flow)return flow;
      }
      if(!(--gap[h[v]]))h[S]=T;
      gap[++h[v]]++;d[v]=g[v];
      return rec;
    }
    void dfs(int x){
      vis[x]=1;
      for(E*p=g[x];p;p=p->nxt)if(p->f&&!vis[p->t])dfs(p->t);
    }
    void solve(int l,int r){
      if(l>=r)return;
      int i;
      for(cur=pool,i=1;i<=T;i++)g[i]=d[i]=NULL,h[i]=gap[i]=0;
      for(i=1;i<=m;i++)add(e[i][0],e[i][1],e[i][2]),add(e[i][1],e[i][0],e[i][2]);
      add(S,a[l],inf),add(a[r],T,inf);
      for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i],vis[i]=0;
      while(h[S]<T)maxflow+=sap(S,inf);
      ans+=maxflow;
      dfs(S);
      int L=l,R=r;
      for(i=l;i<=r;i++)if(vis[a[i]])b[L++]=a[i];else b[R--]=a[i];
      for(i=l;i<=r;i++)a[i]=b[i];
      solve(l,R),solve(L,r);
    }
    int work(){
      S=n+1;T=S+1;
      for(i=1;i<=n;i++)a[i]=i;
      solve(1,n);
      return ans;
    }
    }
    inline int getid(){
      int x,y;
      scanf("%d%d",&x,&y);
      if(T[PI(x,y)])return T[PI(x,y)];
      T[PI(x,y)]=++n;
      a[n]=P(x,y);
      return n;
    }
    int main(){
      scanf("%d",&Case);
      for(cas=1;cas<=Case;cas++){
        n=cnt=0;
        T.clear();
        scanf("%d",&m);
        for(i=0;i<m;i++){
          x=getid();
          y=getid();
          scanf("%d",&z);
          e[i<<1]=E(x,y,z);
          e[i<<1|1]=E(y,x,z);
        }
        for(i=0;i<m+m;i++)del[i]=from[i]=0;
        for(i=1;i<=n;i++)GetArea::g[i].clear();
        for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i);
        GetArea::work();
        GH::init(cnt+1);
        for(i=0;i<m+m;i+=2)GH::newedge(from[i]+1,from[i^1]+1,e[i].z);
        printf("Case #%d: %d
    ",cas,GH::work());
      }
      return 0;
    }
    

      

  • 相关阅读:
    【NYOJ】[168]房间安排
    【NYOJ】[168]房间安排
    【POJ】[3253]Fence Repair
    【POJ】[3253]Fence Repair
    【杭电】[2111]Saving HDU
    【杭电】[2111]Saving HDU
    【杭电】[3635]Dragon Balls
    【杭电】[3635]Dragon Balls
    [leetcode]159. Longest Substring with At Most Two Distinct Characters至多包含两种字符的最长子串
    [leetcode]3. Longest Substring Without Repeating Characters无重复字母的最长子串
  • 原文地址:https://www.cnblogs.com/clrs97/p/7476662.html
Copyright © 2011-2022 走看看