这题码量好大……

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 #include<bits/stdc++.h>
#define mp make_pair using namespace std;
const int inf=;
struct way{int po,next,flow;} e[];
pair<int,int> q[];
int len,n,m,t,mx,pre[],numh[],cur[],h[],d[],p[];
int w[][],hs[][],a[],b[],r[],ans[];
vector<int> g[][];
string s;
bool v[]; void add(int x,int y,int f)
{
e[++len].po=y;
e[len].flow=f;
e[len].next=p[x];
p[x]=len;
}
void build(int x, int y, int f)
{
add(x,y,f);
add(y,x,);
} int sap()
{
memset(h,,sizeof(h));
memset(numh,,sizeof(numh));
numh[]=t+;
for (int i=; i<=t; i++) cur[i]=p[i];
int j,u=,s=,neck=inf;
while (h[]<t+)
{
d[u]=neck;
bool ch=;
for (int i=cur[u]; i!=-; i=e[i].next)
{
j=e[i].po;
if (e[i].flow>&&h[u]==h[j]+)
{
neck=min(neck,e[i].flow);
cur[u]=i;
pre[j]=u; u=j;
if (u==t)
{
s+=neck;
while (u)
{
u=pre[u];
j=cur[u];
e[j].flow-=neck;
e[j^].flow+=neck;
}
neck=inf;
}
ch=;
break;
}
}
if (ch)
{
if (--numh[h[u]]==) return s;
int q=-,tmp=t;
for (int i=p[u]; i!=-; i=e[i].next)
{
j=e[i].po;
if (e[i].flow&&h[j]<tmp)
{
tmp=h[j];
q=i;
}
}
cur[u]=q; h[u]=tmp+;
numh[h[u]]++;
if (u)
{
u=pre[u];
neck=d[u];
}
}
}
return s;
} bool check()
{
t=n; len=-;
memset(p,,sizeof(p));
memset(v,,sizeof(v));
memset(hs,,sizeof(hs));
for (int i=; i<=n; i++) v[b[i]]=;
int can=;
for (int i=; i<=n; i++)
if (v[i])
{
int x=;
if (!w[i][]) x=i;
else x=i-(w[i][]-)%i-;
if (x)
{
hs[i][]=++t; q[t]=mp(i,);
build(,t,x); can+=x;
}
for (int j=; j<r[i]; j++)
if (!w[i][j])
{
hs[i][j]=++t; q[t]=mp(i,j);
build(,t,); can++;
}
}
for (int i=; i<=n; i++)
{
if (a[i]<n+&&b[i]<n+) continue;
if (a[i]==n+&&b[i]==n+)
{
for (int j=n+; j<=t; j++)
build(j,i,);
}
else if (b[i]==n+)
{
for (int j=; j<=n; j++)
if (hs[j][a[i]]) build(hs[j][a[i]],i,);
}
else if (a[i]==n+)
{
for (int j=; j<r[b[i]]; j++)
if (hs[b[i]][j]) build(hs[b[i]][j],i,);
}
build(i,t+,);
}
t++;
if (sap()<can) return ; else return ;
} void print()
{
for (int i=n+; i<t; i++)
for (int j=p[i]; j>-; j=e[j].next)
{
int x=e[j].po;
if (x&&x<=n&&!e[j].flow)
{
a[x]=q[i].second;
b[x]=q[i].first;
}
}
// for (int i=1; i<=n; i++) cout <<a[i]<<" "<<b[i]<<endl;
for (int i=; i<=n; i++)
if (a[i]==n+&&b[i]==n+) {a[i]=; b[i]=;}
else if (a[i]==n+) {a[i]=;}
else if (b[i]==n+)
{
for (int j=; j<=n; j++)
if (r[j]>=a[i]) {b[i]=j; break;}
}
for (int i=; i<=n; i++)
g[b[i]][a[i]].push_back(i);
for (int i=; i<=n; i++)
{
for (int j=; j<g[i][].size(); j+=i)
{
for (int k=j; k<j+i-; k++) ans[g[i][][k]]=g[i][][k+];
ans[g[i][][j+i-]]=g[i][][j];
}
for (int j=; j<=n; j++)
for (int k=; k<g[i][j].size(); k++)
ans[g[i][j][k]]=g[i][j-][];
}
for (int i=; i<=n; i++) printf("%d ",ans[i]);
} int main()
{
scanf("%d\n",&n);
mx=;
for (int i=; i<=n; i++)
{
getline(cin,s);
int l=s.length(),j;
for (j=; j<l; j++)
{
if (s[j]=='?') a[i]=n+;
else if (s[j]==' ') break;
else a[i]=a[i]*+s[j]-'';
}
j++;
for (; j<l; j++)
{
if (s[j]=='?') b[i]=n+;
else if (s[j]==' ') break;
else b[i]=b[i]*+s[j]-'';
}
if (a[i]<n+&&b[i]==n+)
{
if (a[mx]<a[i]) mx=i;
}
else w[b[i]][a[i]]++;
}
for (int i=; i<=n; i++)
for (int j=n; j; j--)
if (w[i][j]) {r[i]=j; break;}
bool ff=;
for (int i=; i<=n; i++)
{
int pr=r[i];
if (r[i]<a[mx])
{
r[i]=a[mx];
b[mx]=i;
}
if (check()) {ff=;break;}
b[mx]=n+; r[i]=pr;
}
if (!ff) puts("-1"); else print();
return ;
}

codeforces 739D的更多相关文章

  1. Codeforces 739D - Recover a functional graph(二分图匹配)

    Codeforces 题面传送门 & 洛谷题面传送门 首先假设我们已经填好了所有问号处的值怎样判断是否存在一个合法的构造方案,显然对于一种方案能够构造出合法的基环内向森林当且仅当: \(\fo ...

  2. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  3. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  4. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  5. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  6. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  7. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  8. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

  9. CodeForces - 696B Puzzles

    http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...

随机推荐

  1. 我的python计划

    一直想学习一种脚本语言.现在主流的脚本语言,比较先接触的是python 刚开始了解了一下python,感觉挺适合自己的感觉,学习了一段时间,之中感觉,就好象C++一样,把面向对象和面向过程编程结合了起 ...

  2. Delphi 7学习开发控件(续)

    继上次我们学习开发一个简单的画线控件后,基本的制作控件步骤已经清楚了,这次我们继续加深学习控件的制作.我们打开Delphi 7创建一个应用程序,拖动LineTo控件到窗体上,仔细看左边的对象设计器,可 ...

  3. Struts1防止表单重复提交

    package org.zln.struts.action; import org.apache.struts.action.Action; import org.apache.struts.acti ...

  4. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  5. [NOIP2017 TG D2T3]列队

    题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$. 现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最 ...

  6. [ZJOI2005]沼泽鳄鱼 矩阵乘法

    ---题面--- 题解: 乍一看还是挺懵逼的.和HH去散步很像,思路也是类似的. 复制一段我在HH去散步的题解里面写的一段话吧: 考虑f[i][j]表示i和j是否右边相连,有为1,否则为0,那么f同时 ...

  7. MFC中ON_UPDATE_COMMAND_UI和ON_COMMAND消息区别

    原文链接地址:http://www.cnblogs.com/orez88/articles/2217823.html 第一个是你打开这个菜单时,处理这个菜单的状态,比如选中.变灰等等.  第二个是响应 ...

  8. picks loves segment tree I

    picks loves segment tree I 题目背景 来源: \(\text {2018 WC Segment Tree Beats}\) 原作者: \(\text {C_SUNSHINE} ...

  9. poj 1201 TYVJ 1415 Intervals

    Description: 给定n个闭区间[ai,bi] 和n个整数ci,你需要构造一个集合Z,使得对于任何的i∈[1,n],Z中满足x∈[ai,bi]的x不少于ci个 求这样的整数集合Z至少包含多少个 ...

  10. HAOI2006 均分数据 [模拟退火]

    题目描述 已知N个正整数:A1.A2.--.An .今要将它们分成M组,使得各组数据的数值和最平均,即各组的均方差最小.均方差公式如下: 输入输出格式 输入格式: 输入文件data.in包括: 第一行 ...