特判与本地能过但是交上去就不对…。
同样是等会儿一块写吧。
题意
有n个城市,一些城市之间两两存在边。要求从城市1出发走到城市n然后再从城市n走到城市1。
要求经过的城市形成一个单调递增+单调递减序列。
求这最长的序列并且输出。
分析
首先考虑转化问题变成从1走到n两次。
然后求最大费用最大流。通过判断是否满流来判断是否存在解。
然后再通过正反各输出一次来输出方案。
大概就没了。
非要有什么注意的就是一开始怎么会想把边变成点呢 大概有点糊涂了orz
code
#include<bits/stdc++.h>
using namespace std;
/*
某一条边正着或者反着只能流一次。
给每一条边再来一个容量...?总之就是限制这条边只能流一次[???]
把边拆成点。然后瞎搞。[????]
还是有很多问题啊。
源点和汇点总不可能是同一个吧。
然后就是怎么瞎搞呢...???
等等好像是我搞错了啊。
是点不能重复两次经过所以是把点拆成边啊。
哦 好像明朗了。
那么就是最大费用流。
然后节点的事情就把所有跟1连的点多连一个汇点。
带环的话SPFA好像跑不动啊...
那把环去掉行不行呢。
从x到y再回x相当于x到y走两次
*/
void read(int &x){
x=0; char c=getchar();
for (;c<48;c=getchar());
for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
string sx,sy,name[105];
#define M 205
struct ed{
int x,cap,cost,nx;
}e[M*M];
#define inf 100000
int nx[M],ecnt;
void add(int x,int y,int cap,int cost){
e[ecnt]=(ed){y,cap,cost,nx[x]};
nx[x]=ecnt++;
e[ecnt]=(ed){x,0,-cost,nx[y]};
nx[y]=ecnt++;
}
int n;
struct EK_EK{
int Q[M],dis[M],s,t,l,r,Flow,Cost,nxt[M];
bool vis[M];
bool spfa(int x){
for (int i=s;i<=t;i++)dis[i]=-inf;
l=r=0;
Q[r++]=x;
dis[x]=0;
for (;l!=r;){
x=Q[l++]; l%=M;
vis[x]=0;
for (int i=nx[x];~i;i=e[i].nx)if (e[i].cap>0&&e[i].cost+dis[x]>dis[e[i].x]){
dis[e[i].x]=dis[x]+e[i].cost; nxt[e[i].x]=i;
if (!vis[e[i].x]){
vis[e[i].x]=1;
Q[r++]=e[i].x; r%=M;
}
}
}
return dis[t]>-inf;
}
int dfs(int x,int f){
if (x==s){
Cost+=f*dis[t];
return f;
}
int res=dfs(e[nxt[x]^1].x,min(f,e[nxt[x]].cap));
e[nxt[x]].cap-=res; e[nxt[x]^1].cap+=res;
return res;
}
void solve(int ss,int tt){
s=ss; t=tt;
for (;spfa(s);)Flow+=dfs(t,inf);
}
void find1(int x) {
cout<<name[x]<<endl;
if(x==n) return;
for(int i=nx[x+n];~i;i=e[i].nx) if(e[i].cost==0&&e[i^1].cap!=0&&e[i].x<=n)
{e[i^1].cap=0,find1(e[i].x);return;}
}
void find2(int x) {
if(x==n) return;
for(int i=nx[x+n];~i;i=e[i].nx) if(e[i].cost==0&&e[i^1].cap!=0&&e[i].x<=n)
{find2(e[i].x);break;}
cout<<name[x]<<endl;
}
void pt(){
find1(1);
find2(1);
}
}EK;
map< string , int >mp;
int main(){
// freopen("LOJ6122.in","r",stdin);
int m,x,y;
read(n); read(m);
memset(nx,-1,sizeof(nx));
int s=0,t=2*n+1;
add(s,1,2,0);
for (int i=1;i<=n;i++){
cin>>name[i];
mp[name[i]]=i;
}
add(n+n,t,2,0);
add(1,n+1,2,1);
add(n,n+n,2,1);
for (int i=2;i<n;i++){
add(i,i+n,1,1);
}
for (int i=1;i<=m;i++){
cin>>sx>>sy;
x=mp[sx]; y=mp[sy];
if (x>y)swap(x,y);
add(x+n,y,1+(x==1&&y==n),0);
}
EK.solve(s,t);
if (EK.Flow==2)printf("%d\n",EK.Cost-2),EK.pt();
else printf("No Solution!\n");
return 0;
}