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
原文地址:https://www.cnblogs.com/phile/p/6363730.html