这题码量好大……
首先思考如何构造,不难找到一下两个条件
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 }