很好的一道題。。。抽出模型是這題關鍵的一步。。。其實可以作爲傳統類題的。。。但是如果有任何關於連通性的描述就會徹底破壞這題的價值。。。所以它就成了提交答案式。。。
我只做了歐拉回路的測試點。。。因爲木有時間了。。。構圖很簡單。。。將入度大於出度的作爲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;
}