链接:https://www.oj.swust.edu.cn/oj/problem/show/1746
题意:给定无向图,求一条从s到t再到s的最长路径,除s外每个点最多经过一次。
分析:实际上相当于求两条从s到t的路径,两条路径互不相交且长度和最大。先拆点,把每个点拆成X和Y,连一条容量为1、费用为-1的边,再求一次最小费用最大流。最大流不为2时无解。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<queue> 6 #include<stack> 7 #include<map> 8 #include<string> 9 using namespace std; 10 typedef long long ll; 11 const int maxn=205,INF=1e9; 12 int n,v; 13 map<string,int> city; 14 string name[maxn]; 15 struct Edge{ 16 int from,to,cap,flow,cost; 17 Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){} 18 }; 19 struct MCMF{ 20 int n,s,t; 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 int inq[maxn],d[maxn],p[maxn],a[maxn]; 24 ll flow,cost; 25 void init(int n){ 26 this->n=n; 27 flow=0,cost=0; 28 for(int i=0;i<n;i++)G[i].clear(); 29 edges.clear(); 30 } 31 32 void AddEdge(int from,int to,int cap,int cost){ 33 edges.push_back(Edge(from,to,cap,0,cost)); 34 edges.push_back(Edge(to,from,0,0,-cost)); 35 G[from].push_back(edges.size()-2); 36 G[to].push_back(edges.size()-1); 37 } 38 39 bool spfa(int s,int t){ 40 this->s=s;this->t=t; 41 for(int i=0;i<n;i++)d[i]=INF; 42 memset(inq,0,sizeof(inq)); 43 d[s]=0;inq[s]=1;p[s]=0;a[s]=INF; 44 queue<int>Q; 45 Q.push(s); 46 while(!Q.empty()){ 47 int u=Q.front();Q.pop(); 48 inq[u]=0; 49 for(int i=0;i<G[u].size();i++){ 50 Edge& e=edges[G[u][i]]; 51 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){ 52 d[e.to]=d[u]+e.cost; 53 p[e.to]=G[u][i]; 54 a[e.to]=min(a[u],e.cap-e.flow); 55 if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;} 56 } 57 } 58 } 59 if(d[t]==INF)return false; 60 flow+=a[t];cost+=d[t]*a[t]; 61 int u=t; 62 while(u!=s){ 63 edges[p[u]].flow+=a[t]; 64 edges[p[u]^1].flow-=a[t]; 65 u=edges[p[u]].from; 66 } 67 return true; 68 } 69 ll Mincost(int s,int t){ 70 while(spfa(s,t)); 71 return cost; 72 } 73 void Print(int n){ 74 int have[maxn]; 75 memset(have,0,sizeof(have)); 76 cout<<name[1]<<endl; 77 int u=s+n; 78 while(u!=t+n){ 79 for(int i=0;i<G[u].size();i++){ 80 Edge &e=edges[G[u][i]]; 81 if(e.flow>=1&&have[e.to]==0){ 82 have[e.to]=1; 83 cout<<name[e.to]<<endl; 84 u=e.to+n;break; 85 } 86 } 87 if(u==s+n)break; 88 } 89 u=n; 90 while(u!=s){ 91 for(int i=0;i<G[u].size();i++){ 92 Edge &e=edges[G[u][i]^1]; 93 if(e.flow>=1&&have[e.from-n]==0){ 94 have[e.from-n]=1; 95 cout<<name[e.from-n]<<endl; 96 u=e.from-n;break; 97 } 98 } 99 if(u==n)break; 100 } 101 } 102 }mcmf; 103 int main(){ 104 // freopen("e:\in.txt","r",stdin); 105 string s,t; 106 scanf("%d%d",&n,&v); 107 mcmf.init(2*n); 108 mcmf.AddEdge(1,1+n,2,0); 109 for(int i=2;i<n;i++)mcmf.AddEdge(i,i+n,1,-1); 110 for(int i=1;i<=n;i++){ 111 cin>>s; 112 city[s]=i; 113 name[i]=s; 114 } 115 for(int i=0;i<v;i++){ 116 cin>>s>>t; 117 mcmf.AddEdge(city[s]+n,city[t],INF,0); 118 } 119 int ans=2-mcmf.Mincost(1,n); 120 if(mcmf.flow!=2){ 121 printf("No Solution! "); 122 }else{ 123 printf("%d ",ans); 124 mcmf.Print(n); 125 } 126 return 0; 127 }