调了半天最后发现费用流部分一个小细节跪了。。。
心态爆炸。。。问题不大
首先我们直接找出两条没有重复节点的路径,一条正着输出一条倒着输出就行了。
找的话考虑网络流。我们将每个点拆点成两个 a i , b i a_i,b_i ai,bi,为保证每个城市只在路径中出现一次,我们从 a i a_i ai向 b i b_i bi连一条容量为 1 1 1的边,但是注意节点 1 1 1和节点 n n n需要连容量为 2 2 2的边,因为需要两条路径。
对于每条边 < u , v > <u,v> <u,v>我们从 b u b_u bu向 a v a_v av连边,容量为 1 1 1,这个是路径存在性问题的老套路了。
如果最后跑出来的最大流为0,则根本不存在从 1 1 1到 n n n的路径。
否则,一定存在。
为了使经过的城市最多,我们在每个 a i a_i ai到 b i b_i bi的边上赋费用为 1 1 1,即要求最大费用,使得这个城市被经过就有一份费用被记录在答案中。(转成-1求最小费用)
那么最大费用减去在 1 1 1和 n n n的两次经过,就是经过的城市数。
怎么找路径?
考虑我们走过的路径才会有流量,那么它的反向边的流量就是我们经过它的次数,直接从源点dfs一下,同时清空一下流量就行了。
代码:
#include
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
cs int N=203,M=20004,INF=0x3f3f3f3f;
int last[N],nxt[M<<1],to[M<<1],ecnt=1;
int cap[M<<1],w[M<<1];
inline void addedge(int u,int v,int val,int cost){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,cap[ecnt]=val,w[ecnt]=cost;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,cap[ecnt]= 0 ,w[ecnt]=-cost;
}
int S,T;
int dist[N];
int cur[N];
bool vis[N];
queue<int> q;
inline bool SPFA(){
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
dist[S]=0;
q.push(S);
cur[S]=last[S];
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(cap[e]&&dist[v]>dist[u]+w[e]){
dist[v]=dist[u]+w[e];
if(!vis[v]){
vis[v]=true;
q.push(v);
cur[v]=last[v];
}
}
}
}
return dist[T]<INF;
}
int dfs(cs int &u,cs int &flow,int &maxc){
if(u==T){
maxc+=flow*dist[T];
return flow;
}
int ans=0;
vis[u]=true;
for(int &e=cur[u],v=to[e];e;v=to[e=nxt[e]]){
if(cap[e]&&!vis[v]&&dist[v]==dist[u]+w[e]){
int delta=dfs(v,min(flow-ans,cap[e]),maxc);
if(delta){
cap[e]-=delta;
cap[e^1]+=delta;
ans+=delta;
if(ans==flow)return flow;
}
}
}
return ans;
}
int maxf,maxc;
inline pair<int,int> MCMF(){
maxf=0;maxc=0;
while(SPFA())maxf+=dfs(S,INF,maxc);
return make_pair(maxf,maxc);
}
map<string,int> id;
string name[N>>1],s1,s2;
int n,m;
int ans[N],tot;
void getans(int u){
ans[++tot]=u;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(e&1)continue;
if(cap[e^1]){
--cap[e^1];
getans(v);
return ;
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int re i=1;i<=n;++i){
cin>>name[i];
id[name[i]]=i;
}
S=0,T=n+n+1;
addedge(S,1,2,0);
addedge(1,1+n,1,-1);
addedge(n,n+n,1,-1);
addedge(n+n,T,2,0);
for(int re i=1;i<=m;++i){
cin>>s1>>s2;
int u=id[s1],v=id[s2];
if(u>v)swap(u,v);
addedge(u+n,v,INF,0);
}
for(int re i=1;i<=n;++i)addedge(i,i+n,1,-1);
MCMF();
if(maxf==0)return cout<<"No Solution!\n",0;
cout<<(-maxc-2)<<"\n";
getans(1);
for(int re i=1;i<=tot;++i)if(ans[i]&&ans[i]<=n)cout<<name[ans[i]].c_str()<<endl;
tot=0;
getans(1);
bool flag=0;
for(int re i=tot;i;--i){
if(ans[i]&&ans[i]<=n)
if(flag)cout<<name[ans[i]].c_str()<<endl;
else flag=true;
}
return 0;
}