洛谷2270航空路線問題
阿新 • • 發佈:2018-12-27
題目連結:航空路線問題
由題目中的“每一個城市最多經過一次”可知需要拆點
在根據所求經過城市數最多將城市拆成的邊的容量設為1,費用設為1
同時以\(n\)為匯點,源點到1和1中的兩點的容量均設為2
再將原圖中的邊的容量設為\(INF\),費用為0
跑最大費用最大流
輸出方案的話,從1開始dfs出兩條路徑即可,注意不要經過重邊以及加入點的合法性
初始化的話可以將所有的name加入至一個map中(常數++)
#include<iostream> #include<string> #include<string.h> #include<stdio.h> #include<algorithm> #include<math.h> #include<vector> #include<queue> #include<map> using namespace std; #define rep(i,a,b) for (i=a;i<=b;i++) typedef long long ll; #define maxd 1e9+7 struct node{ int to,nxt,cost,flow; }sq[100100]; int n,m,all=1,head[100100],dis[100100],pre[100100],s,t,maxf=0,minc=0, flow[100100],ans[100100],tot=0; bool vis[100100]; string name[110]; map<string,int> mp; void add(int u,int v,int f,int w) { all++;sq[all].to=v;sq[all].nxt=head[u];sq[all].cost=w;sq[all].flow=f;head[u]=all; all++;sq[all].to=u;sq[all].nxt=head[v];sq[all].cost=-w;sq[all].flow=0;head[v]=all; } bool spfa() { queue<int> q;int i; for (i=1;i<=2*n-1;i++) dis[i]=maxd;dis[s]=0; memset(vis,0,sizeof(vis)); memset(flow,0,sizeof(flow)); vis[s]=1;q.push(s);flow[s]=maxd; while (!q.empty()) { int u=q.front();q.pop();vis[u]=0; for (i=head[u];i;i=sq[i].nxt) { int v=sq[i].to; if ((sq[i].flow) && (dis[v]>dis[u]+sq[i].cost)) { dis[v]=sq[i].cost+dis[u];pre[v]=i; flow[v]=min(flow[u],sq[i].flow); if (!vis[v]) { vis[v]=1;q.push(v); } } } } return (dis[t]!=maxd); } void update() { int now=t; maxf+=flow[t]; minc+=(flow[t]*dis[t]); while (now!=s) { int tmp=pre[now]; sq[tmp].flow-=flow[t]; sq[tmp^1].flow+=flow[t]; now=sq[tmp^1].to; } } int read() { int x=0,f=1;char ch=getchar(); while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();} while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();} return x*f; } void init() { ios::sync_with_stdio(0); cin >> n >> m;s=0;t=n;int i; add(s,1,2,0); for (i=1;i<=n;i++) { cin >> name[i]; mp[name[i]]=i; if ((i!=1) && (i!=n)) add(i,i+n,1,-1); } add(1,n+1,2,0); for (i=1;i<=m;i++) { string from,to; cin >> from >> to; int u=mp[from],v=mp[to]; //cout << u << " " << v << endl; if (u>v) swap(u,v); add(u+n,v,maxd,0); } } void out(int u) { ans[++tot]=u;int i; if (u==n) return; for (i=head[u+n];i;i=sq[i].nxt) { int v=sq[i].to; if ((!vis[i]) && (sq[i^1].flow)) {vis[i]=1;out(v);return;} } } void work() { while (spfa()) update(); if (maxf<2) {cout << "No Solution!";return;} cout << 2-minc << endl; tot=0;int i; memset(vis,0,sizeof(vis)); out(1); for (i=1;i<=tot;i++) if ((ans[i]<=n) && (ans[i])) cout << name[ans[i]] << endl; tot=0; out(1); for (i=tot;i>=1;i--) if (ans[i]<n) cout << name[ans[i]] << endl; } int main() { init(); work(); return 0; }