很好的一道题。。。抽出模型是这题关键的一步。。。其实可以作为传统类题的。。。但是如果有任何关于连通性的描述就会彻底破坏这题的价值。。。所以它就成了提交答案式。。。
我只做了欧拉回路的测试点。。。因为木有时间了。。。构图很简单。。。将入度大于出度的作为A类,入度小于出度的为B类。。。源向A连边,流量为in-out,B向汇连边,流量为out-in。。。中间的为oo,费用分情况讨论。。。(abc)->(bcd)为1,(abc)->(cde)为2,(abc)->(def)为3。。。
最后输出方案时注意,由于你求的是回路。。。那么首尾点一定是同一个点。。。对于倒数第二个点。。。有可能会与第一个点有重复的地方,也要去掉。。。
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
const int source=1000,sink=1001,maxm=2020055;
typedef long long ll;
int e=1,ed=1,top=0,tail=0,m=0,len=0,tot=0,totlen=0;
int head[1005],now[1005],link[maxm],next[maxm],cost[maxm],dis[1005],sta[maxm*3],pre[1005],list[maxm],ans[maxm];
ll w[maxm],d1[1005],d2[1005],g[1005][1005];
bool vis[1005];
bool spfa()
{
top=0;
sta[tail=1]=source;
memset(vis,0,sizeof(vis));
memset(dis,65,sizeof(dis));
memset(pre,0,sizeof(pre));
int oo=dis[0]-1,x=0,y=0,ne=0;
dis[source]=0;
vis[source]=1;
while (top<tail)
{
x=sta[++top];
for (ne=head[x],y=link[ne];ne;ne=next[ne],y=link[ne])
if (w[ne])
if (dis[x]+cost[ne]<dis[y])
{
dis[y]=dis[x]+cost[ne];
if (!vis[y])
sta[++tail]=y,vis[y]=1;
pre[y]=x;
now[y]=ne;
}
vis[x]=0;
}
if (dis[sink]<oo) return 1;
return 0;
}
void add(int u,int v,ll tmpw,int tmpc)
{
next[++e]=head[u];
head[u]=e;
link[e]=v;
w[e]=tmpw;
cost[e]=tmpc;
next[++e]=head[v];
head[v]=e;
link[e]=u;
w[e]=0;
cost[e]=-tmpc;
}
int get()
{
int nop=sink;
ll flows=2000000000;
for (;nop!=source;nop=pre[nop])
if (flows>w[now[nop]])
flows=w[now[nop]];
for (nop=sink;nop!=source;nop=pre[nop])
w[now[nop]]-=flows,w[now[nop]^1]+=flows;
return flows*dis[sink];
}
void dfs(int i)
{
for (int j=0;j<=999;j++)
if (g[i][j])
{
g[i][j]--;
dfs(j);
}
list[++len]=i;
}
int main(int argc,char *argv[])
{
char inname[200],outname[200];
memset(inname,0,sizeof(inname));
memset(outname,0,sizeof(outname));
sprintf(inname,"password%s.in",argv[1]);
sprintf(outname,"password%s.out",argv[1]);
freopen(inname,"r",stdin);
freopen(outname,"w",stdout);
scanf("%d",&m);
int i=0,j=0;
int ch=0,pres=0,nows=0;
for (i=1;i<=m;i++)
{
scanf("%d",&ch);
pres=ch/10;
nows=ch%1000;
if (!g[pres][nows])
{
g[pres][nows]=1;
d1[pres]++;
d2[nows]++;
totlen++;
}
}
int tmpc=0;
for (i=0;i<=999;i++)
if (d1[i]>d2[i])
for (j=0;j<=999;j++)
if (d2[j]>d1[j])
{
if ((j%100)==(i/10))
tmpc=1;
else
if ((j%10)==(i/100))
tmpc=2;
else
tmpc=3;
add(j,i,2000000000,tmpc);
}
for (i=0;i<=999;i++)
if (d2[i]>d1[i])
add(source,i,d2[i]-d1[i],0);
else
if (d1[i]>d2[i])
add(i,sink,d1[i]-d2[i],0);
while (spfa()) totlen+=get();
int ne=0;
for (i=0;i<=999;i++)
if (d2[i]>d1[i])
for (ne=head[i];ne;ne=next[ne])
if (!(ne&1))
g[i][link[ne]]+=w[ne^1];
len=0;
for (i=0;i<=999;i++)
if (d1[i]+d2[i]>0)
{
dfs(i);
break;
}
len--;
tot=3;
ans[1]=list[len]/100;
ans[2]=(list[len]/10)%10;
ans[3]=list[len]%10;
for (i=len-1;i>=1;i--)
{
if ((list[i+1]%100)==(list[i]/10))
{
tot++;
ans[tot]=list[i]%10;
}
else
if ((list[i+1]%10)==(list[i]/100))
{
tot+=2;
ans[tot-1]=(list[i]/10)%10;
ans[tot]=list[i]%10;
}
else
{
tot+=3;
ans[tot-2]=list[i]/100;
ans[tot-1]=(list[i]/10)%10;
ans[tot]=list[i]%10;
}
}
printf("%d\n",totlen);
for (i=1;i<=totlen;i++)
printf("%d",ans[i]);
return 0;
}