题解:分析一下,要求往返经过最多点的路径,可以转化为求两条从s到t的不相交的尽量长的路径,根据要求限制,无向边变成有向边。求两条不相交的路径,将每个点拆开(x,x’),可以用网络流。又要尽量长,可以用最大费用最大流。
有解无解判断一下是否最大流是否等于2。输出路径需要遍历所有的边流完的边。
#include
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int n,m;
map<string,int> mp;
map<int,string> np;
char tmp[200][200],s1[200],s2[200];
vector<int> g[maxn];
vector<int> a[3];
struct ss{
int u,v,c,w,nxt;
}edg[maxn];
int head[maxn],cnt,d[maxn],vis[maxn],pre[maxn];
void init() {
cnt = 0;
memset(head,-1,sizeof head);
}
void add(int u,int v,int c,int w) {
edg[cnt].u = u;
edg[cnt].v = v;
edg[cnt].c = c;
edg[cnt].w = w;
edg[cnt].nxt = head[u];
head[u] = cnt++;
}
bool spfa(int s,int t) {
queue<int> q;
memset(vis,0,sizeof vis);
memset(d,-inf,sizeof d);
memset(pre,-1,sizeof pre);
q.push(s);
d[s] = 0;vis[s] = 1;
while(!q.empty()) {
int top = q.front();
q.pop();
vis[top] = 0;
for(int i = head[top]; i + 1; i = edg[i].nxt) {
int v = edg[i].v,c = edg[i].c,w = edg[i].w;
if(c && d[v] < d[top] + w) {
d[v] = d[top] + w;pre[v] = i;
if(!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
return pre[t] != -1;
}
int maxflow(int s,int t,int &cost) {
int ans = 0;
cost = 0;
spfa(s,t);
while(spfa(s,t)) {
int mx = inf;
for(int i = pre[t]; i != -1; i = pre[edg[i ^ 1].v]) {
// printf("%d\n",edg[i].v);
mx = min(mx,edg[i].c);
}
for(int i = pre[t]; i != -1; i = pre[edg[i ^ 1].v]) {
edg[i].c -= mx;
edg[i ^ 1].c += mx;
cost += mx * edg[i].w;
}
//printf("%d\n",mx);
ans += mx;
}
return ans;
}
void dfs(int s,int t,int sz) {
//printf("%d ",s);
vis[s] = 1;
if(s == t) return;
for(int i = 0; i < g[s].size(); i++) {
int v = g[s][i];
if(!vis[v]) {
vis[v] = 1;
a[sz].push_back(v);
dfs(v,t,sz);
break;
}
}
}
int main() {
init();
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
scanf("%s",tmp[i]);
mp[tmp[i]] = i;
}
for(int i = 1; i <= m; i++) {
scanf("%s%s",&s1,&s2);
int u = mp[s1],v = mp[s2];
if(u > v) swap(u,v);
if(u == 1 && v == n) {
add(u + n,v,2,1);
add(v,u + n,0,-1);
}
else {
add(u + n,v,1,1);
add(v,u + n,0,-1);
}
}
for(int i = 1; i <= n; i++) {
if(i == 1 || i == n) {
add(i,i + n,2,0);
add(i + n,i,0,0);
}
else {
add(i,i + n,1,0);
add(i + n,i,0,0);
}
}
int cost,f;
f = maxflow(1,n,cost);
if(f != 2)
puts("No Solution!");
else {
printf("%d\n",cost);
for(int i = 1; i <= n; i++)
for(int j = head[i + n]; j + 1; j = edg[j].nxt) {
int c = edg[j].c;
if(!c && i != edg[j].v)
g[i].push_back(edg[j].v);
}
memset(vis,0,sizeof vis);
printf("%s\n",tmp[1]);
dfs(1,n,0);
for(int i = 0; i < a[0].size(); i++)
printf("%s\n",tmp[a[0][i]]);
dfs(1,n,1);
for(int i = a[1].size() - 1; i >= 0; i--)
printf("%s\n",tmp[a[1][i]]);
printf("%s\n",tmp[1]);
}
return 0;
}