洛谷P2770 航空路線問題 最大費用最大流

2021-08-15 18:23:25 字數 1807 閱讀 3424

題目描述

給定一張航空圖,圖中頂點代表城市,邊代表 2 城市間的直通航線。現要求找出一條滿足下述限制條件的且途經城市最多的旅行路線。

(1)從最西端城市出發,單向從西向東途經若干城市到達最東端城市,然後再單向從東向西飛回起點(可途經若干城市)。

(2)除起點城市外,任何城市只能訪問 1 次。

對於給定的航空圖,試設計乙個演算法找出一條滿足要求的最佳航空旅行路線.

題解這道題目按我的理解就是求乙個包含頭結點和尾節點的乙個最大環。

所以我們可以把這個環拆成兩條從頭結點到尾節點的路徑,那麼使這兩條路徑長度相加-2最長即可。

我們來拆點,把i城市拆成入點u_i,出點v_i。那麼x->y有一條邊,便從v_y向u_x連一條流量為inf,費用為0的邊,因為走邊不用消耗費用。

既然要求最長,那麼我們就要從原來的最小費用最大流,改為最大費用最大流。

有人肯定想問,那在spfa求最長路的時候應該怎麼做,很簡單,我們把邊權改負就行了。

每個點的入點u_i到每個點的出點v_i建一條流量為1,費用為-1的邊,表示飛機只能在這個城市中轉一次(只能經過這個城市一次),費用總數的絕對值便是經過城市總數,不要忘記減2。因為頭結點和尾節點都是經過兩次的。

但是1和n的這樣的邊要建兩條,因為這樣才能把流量分出去。

begin源點到u_1建一條流量為2,費用為0的邊,表示要找到兩條從起點到終點的路徑。

v_n到end匯點建一條流量為2,費用為0的邊,同理。

下列情況要特判:

1.只經過最東端城市和最西端城市,不用減2.

2.在dfs輸出答案時,記得掌握好這條邊是否走過的判斷依據。

**有點醜,主要還是掌握思路哈

#include #include #include #include #include #include #include #define inf 1e9

using namespace std;

int n,m;

struct edge;

edge s[10010];

mappei;

int first[210];

int ip[210];

int len=1;

int begin,end;

int h[210],min_flow[210];

queuef;

int answer[2][210];

int tan=0,tans=0;

string fact[110];

bool tf[210];

int last=0;

int mmin(int x,int y)

}} }

if(h[end]==1061109567) return 0;

flow+=min_flow[end];

cost+=-h[end]*min_flow[end];

int now=end;

while(now!=begin)

return 1;

}int cost_flow()

void dfs_1(int x)

for(int i=1;i<=m;i++)

ins(1,n+1,1,-1);

ins(n,n+n,1,-1);

ins(begin,1,2,0);

ins(2*n,end,2,0);

int p=cost_flow();

if(p==0) printf("no solution!");

else

{ printf("%d\n",p);

int x=1;

cout<

洛谷 P2770 航空路線問題

給定一張航空圖,圖中頂點代表城市,邊代表 2 城市間的直通航線。現要求找出一條滿足下述限制條件的且途經城市最多的旅行路線。1 從最西端城市出發,單向從西向東途經若干城市到達最東端城市,然後再單向從東向西飛回起點 可途經若干城市 2 除起點城市外,任何城市只能訪問 1 次。對於給定的航空圖,試設計乙個...

洛谷P2770 航空路線問題(費用流)

傳送門 完了這題好厲害 字串什麼的好麻煩 要求從 1 到 n 的路徑,不重複,經過邊數最多 每乙個點拆成兩個,a i,b i 然後 a i 到 b i 連容量為 1 費用為 1 的邊,保證每個點只被選一次 然後 1 和 n 的話要容量為 2 然後有連邊的話,b i 向 a j 連邊,容量 1 費用 ...

P2770 航空路線問題(最大費用最大流)

題意 給定一張航空圖,圖中頂點代表城市,邊代表 2 城市間的直通航線。現要求找出一條滿足下述限制條件的且途經城市最多的旅行路線。1 從最西端城市出發,單向從西向東途經若干城市到達最東端城市,然後再單向從東向西飛回起點 可途經若干城市 2 除起點城市外,任何城市只能訪問 1 次。對於給定的航空圖,試設...