时空限制1000ms / 128MB
题目描述
给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。
(2)除起点城市外,任何城市只能访问 1 次。
对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。
输入输出格式
输入格式:第 1 行有 2 个正整数 N 和 V,N 表示城市数,N<100,V 表示直飞航线数。
接下来的 N 行中每一行是一个城市名,可乘飞机访问这些城市。城市名出现的顺序是从西向东。也就是说,设 i,j 是城市表列中城市出现的顺序,当 i>j 时,表示城市 i 在城市 j 的东边,而且不会有 2 个城市在同一条经线上。城市名是一个长度不超过15 的字符串,串中的字符可以是字母或阿拉伯数字。例如,AGR34 或 BEL4。
再接下来的 V 行中,每行有 2 个城市名,中间用空格隔开,如 city1 city2 表示 city1到 city2 有一条直通航线,从 city2 到 city1 也有一条直通航线。
输出格式:件第 1 行是旅行路线中所访问的城市总数 M。 接下来的 M+1 行是旅行路线的城市名,每行写 1 个城市名。首先是出发城市名,然后按访问顺序列出其它城市名。 注意,最后 1 行(终点城市)的城市名必然是出发城市名。如果问题无解,则输出“No Solution!”。
输入输出样例
说明
题目链接:https://www.luogu.org/problemnew/show/P2770
最大权不相交路径。一开始我没想到竟然可以看成从左端点开始的两条不相交路径,瞎搞了好久。。。
#include<bits/stdc++.h> #define INF LLONG_MAX/2 #define N 205 using namespace std; struct ss { int u,v,next; long long flow,cost; }; ss edg[N*N]; int head[N],now_edge=0; void addedge(int u,int v,long long flow,long long cost) { cost=-cost; edg[now_edge]=(ss){u,v,head[u],flow,cost}; head[u]=now_edge++; edg[now_edge]=(ss){v,u,head[v],0,-cost}; head[v]=now_edge++; } int spfa(int s,int t,long long &flow,long long &cost) { int vis[N]={0}; vis[s]=1; queue<int>q; q.push(s); long long dis[N]; for(int i=0;i<N;i++)dis[i]=INF; dis[s]=0; int pre[N]={0}; long long addflow[N]={0}; addflow[s]=INF; while(!q.empty()) { int now=q.front(); q.pop(); vis[now]=0; for(int i=head[now];i!=-1;i=edg[i].next) { ss e=edg[i]; if(e.flow>0&&dis[e.v]>dis[now]+e.cost) { dis[e.v]=dis[now]+e.cost; pre[e.v]=i; addflow[e.v]=min(e.flow,addflow[now]); if(!vis[e.v]) { q.push(e.v); vis[e.v]=1; } } } } if(dis[t]==INF)return 0; flow+=addflow[t]; cost+=addflow[t]*dis[t]; int now=t; while(now!=s) { edg[pre[now]].flow-=addflow[t]; edg[pre[now]^1].flow+=addflow[t]; now=edg[pre[now]].u; } return 1; } void mcmf(int s,int t,long long &flow,long long &cost) { while(spfa(s,t,flow,cost)); } void init() { now_edge=0; memset(head,-1,sizeof(head)); } map<string,int>Map1; map<int,string>Map2; vector<int>ans; int n; void dfs(int x) { if(x==n)return; int u=x*2; for(int i=head[u];i!=-1;i=edg[i].next) { if(edg[i^1].flow&&edg[i].v!=u-1) { edg[i^1].flow--; ans.push_back(edg[i].v/2+1); dfs(edg[i].v/2+1); return; } } } int main() { init(); int m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { string a; cin>>a; Map1.insert(pair<string,int>(a,i)); Map2.insert(pair<int,string>(i,a)); } int s=2*n+1,t=s+1; while(m--) { string a,b; cin>>a>>b; int u=min(Map1[a],Map1[b]),v=max(Map1[a],Map1[b]); addedge(u*2,v*2-1,INF,0); } for(int i=2;i<n;i++)addedge(i*2-1,i*2,1,1); addedge(1,2,2,1); addedge(2*n-1,2*n,2,1); addedge(s,1,2,0); addedge(2*n,t,INF,0); long long flow=0,cost=0; mcmf(s,t,flow,cost); if(flow<2) { printf("No Solution!\n"); return 0; } printf("%lld\n",-cost-2); dfs(1); cout<<Map2[1]<<endl; for(int i=0;i<ans.size();i++)cout<<Map2[ans[i]]<<endl; ans.clear(); dfs(1); for(int i=ans.size()-2;i>=0;i--)cout<<Map2[ans[i]]<<endl; cout<<Map2[1]<<endl; return 0; }