zoukankan      html  css  js  c++  java
  • codeforces 739D

    这题码量好大……

    首先思考如何构造,不难找到一下两个条件

    1. 在长度为i的环上的点一定是i的倍数个

    2. 到达长度i的环的点集距离一定是连续的

    第一个条件是很好搞的,关键是第二个条件。

    因为存在着x ?这样的点,我们不知道到达环长度为i的点precycle能会连续延伸

    但是观察可知,我们只要找出x ?类点中x最大的点xmax,穷举最终走到环的长度,

    这样其他比xmax小的x ?点肯定都接到这个环上最有可能出解,那么到达每种环长度的precycle界限就确定了

    这样我们就可以建图匹配来判定是否可行了,一侧条件一侧点连边看是否满流即可。

    找出条件点流向的点,我们就能确定这些点的?是什么了

    那么还有些点没用到应该怎么替换?呢

    ? ?的点直接构造一元环,x ?接在可行处,? x直接零?为1

    而我们确定所有点的precycle和cycle后,是很容易构造最终出边的:

    只要把环建好,其他在环上一个点下挂成一个简单树形即可

    思路不难,写起来比较麻烦

      1 #include<bits/stdc++.h>
      2 #define mp make_pair
      3 
      4 using namespace std;
      5 const int inf=1000000007;
      6 struct way{int po,next,flow;} e[2000010];
      7 pair<int,int> q[1010];
      8 int len,n,m,t,mx,pre[1010],numh[1010],cur[1010],h[1010],d[1010],p[1010];
      9 int w[310][310],hs[310][310],a[310],b[310],r[310],ans[310];
     10 vector<int> g[310][310];
     11 string s;
     12 bool v[310];
     13 
     14 void add(int x,int y,int f)
     15 {
     16      e[++len].po=y;
     17      e[len].flow=f;
     18      e[len].next=p[x];
     19      p[x]=len;
     20 }
     21 void build(int x, int y, int f)
     22 {
     23      add(x,y,f);
     24      add(y,x,0);
     25 }
     26 
     27 int sap()
     28 {
     29     memset(h,0,sizeof(h));
     30     memset(numh,0,sizeof(numh));
     31     numh[0]=t+1;
     32     for (int i=0; i<=t; i++) cur[i]=p[i];
     33     int j,u=0,s=0,neck=inf;
     34     while (h[0]<t+1)
     35     {
     36           d[u]=neck;
     37           bool ch=1;
     38           for (int i=cur[u]; i!=-1; i=e[i].next)
     39           {
     40               j=e[i].po;
     41               if (e[i].flow>0&&h[u]==h[j]+1)
     42               {
     43                  neck=min(neck,e[i].flow);
     44                  cur[u]=i;
     45                  pre[j]=u;  u=j;
     46                  if (u==t)
     47                  {
     48                     s+=neck;
     49                     while (u)
     50                     {
     51                           u=pre[u];
     52                           j=cur[u];
     53                           e[j].flow-=neck;
     54                           e[j^1].flow+=neck;
     55                     }
     56                     neck=inf;
     57                  }
     58                  ch=0;
     59                  break;
     60               }
     61           }
     62           if (ch)
     63           {
     64              if (--numh[h[u]]==0) return s;
     65              int q=-1,tmp=t;
     66              for (int i=p[u]; i!=-1; i=e[i].next)
     67              {
     68                  j=e[i].po;
     69                  if (e[i].flow&&h[j]<tmp)
     70                  {
     71                     tmp=h[j];
     72                     q=i;
     73                  }
     74              }
     75              cur[u]=q; h[u]=tmp+1;
     76              numh[h[u]]++;
     77              if (u)
     78              {
     79                 u=pre[u];
     80                 neck=d[u];
     81              }
     82           }
     83     }
     84     return s;
     85 }
     86 
     87 bool check()
     88 {
     89     t=n; len=-1;
     90     memset(p,255,sizeof(p));
     91     memset(v,0,sizeof(v));
     92     memset(hs,0,sizeof(hs));
     93     for (int i=1; i<=n; i++) v[b[i]]=1;
     94     int can=0;
     95     for (int i=1; i<=n; i++)
     96         if (v[i])
     97         {
     98             int x=0;
     99             if (!w[i][0]) x=i;
    100             else x=i-(w[i][0]-1)%i-1;
    101             if (x)
    102             {
    103                 hs[i][0]=++t; q[t]=mp(i,0);
    104                 build(0,t,x); can+=x;
    105             }
    106             for (int j=1; j<r[i]; j++)
    107                 if (!w[i][j])
    108                 {
    109                     hs[i][j]=++t; q[t]=mp(i,j);
    110                     build(0,t,1); can++;
    111                 }
    112         }
    113     for (int i=1; i<=n; i++)
    114     {
    115         if (a[i]<n+1&&b[i]<n+1) continue;
    116         if (a[i]==n+1&&b[i]==n+1)
    117         {
    118             for (int j=n+1; j<=t; j++)
    119                 build(j,i,1);
    120         }
    121         else if (b[i]==n+1)
    122         {
    123             for (int j=1; j<=n; j++)
    124                 if (hs[j][a[i]]) build(hs[j][a[i]],i,1);
    125         }
    126         else if (a[i]==n+1)
    127         {
    128             for (int j=0; j<r[b[i]]; j++)
    129                 if (hs[b[i]][j]) build(hs[b[i]][j],i,1);
    130         }
    131         build(i,t+1,1);
    132     }
    133     t++;
    134     if (sap()<can) return 0; else return 1;
    135 }
    136 
    137 void print()
    138 {
    139     for (int i=n+1; i<t; i++)
    140         for (int j=p[i]; j>-1; j=e[j].next)
    141         {
    142             int x=e[j].po;
    143             if (x&&x<=n&&!e[j].flow)
    144             {
    145                 a[x]=q[i].second;
    146                 b[x]=q[i].first;
    147             }
    148         }
    149   //  for (int i=1; i<=n; i++) cout <<a[i]<<" "<<b[i]<<endl;
    150     for (int i=1; i<=n; i++)
    151         if (a[i]==n+1&&b[i]==n+1) {a[i]=0; b[i]=1;}
    152         else if (a[i]==n+1) {a[i]=1;}
    153         else if (b[i]==n+1)
    154         {
    155             for (int j=1; j<=n; j++)
    156                 if (r[j]>=a[i]) {b[i]=j; break;}
    157         }
    158     for (int i=1; i<=n; i++)
    159         g[b[i]][a[i]].push_back(i);
    160     for (int i=1; i<=n; i++)
    161     {
    162         for (int j=0; j<g[i][0].size(); j+=i)
    163         {
    164             for (int k=j; k<j+i-1; k++) ans[g[i][0][k]]=g[i][0][k+1];
    165             ans[g[i][0][j+i-1]]=g[i][0][j];
    166         }
    167         for (int j=1; j<=n; j++)
    168             for (int k=0; k<g[i][j].size(); k++)
    169                 ans[g[i][j][k]]=g[i][j-1][0];
    170     }
    171     for (int i=1; i<=n; i++) printf("%d ",ans[i]);
    172 }
    173 
    174 int main()
    175 {
    176     scanf("%d
    ",&n);
    177     mx=0;
    178     for (int i=1; i<=n; i++)
    179     {
    180         getline(cin,s);
    181         int l=s.length(),j;
    182         for (j=0; j<l; j++)
    183         {
    184             if (s[j]=='?') a[i]=n+1;
    185             else if (s[j]==' ') break;
    186             else a[i]=a[i]*10+s[j]-'0';
    187         }
    188         j++;
    189         for (; j<l; j++)
    190         {
    191             if (s[j]=='?') b[i]=n+1;
    192             else if (s[j]==' ') break;
    193             else b[i]=b[i]*10+s[j]-'0';
    194         }
    195         if (a[i]<n+1&&b[i]==n+1)
    196         {
    197             if (a[mx]<a[i]) mx=i;
    198         }
    199         else w[b[i]][a[i]]++;
    200     }
    201     for (int i=1; i<=n; i++)
    202         for (int j=n; j; j--)
    203             if (w[i][j]) {r[i]=j; break;}
    204     bool ff=0;
    205     for (int i=1; i<=n; i++)
    206     {
    207         int pr=r[i];
    208         if (r[i]<a[mx])
    209         {
    210             r[i]=a[mx];
    211             b[mx]=i;
    212         }
    213         if (check()) {ff=1;break;}
    214         b[mx]=n+1; r[i]=pr;
    215     }
    216     if (!ff) puts("-1"); else print();
    217     return 0;
    218 }
    View Code
  • 相关阅读:
    二维数组和指向指针的指针
    多路复用构建高性能服务器
    disque概要
    漫谈云计算与SOA (1)
    zeromq
    自定义内存分配
    基于行的操作
    反应器类型的操作
    多个流,简短的读和写
    缓存
  • 原文地址:https://www.cnblogs.com/phile/p/6363730.html
Copyright © 2011-2022 走看看