題目大意:
給定一張航空圖,圖中頂點代表城市,邊代表 2 城市間的直通航線。現要求找出一條滿足下述限制條件的且途經城市最多的旅行路線。
(1)從最西端城市出發,單向從西向東途經若干城市到達最東端城市,然後再單向從東向西飛回起點(可途經若干城市)。
(2)除起點城市外,任何城市只能訪問 1 次。
關鍵字:網路流 方向等效轉換 拆點 不交叉路徑 特判
網路流:1個人旅行的過程可以看作以流量為1流動的過程。
方向等效轉化:本問題可以看作兩個人同時從最西的城市走向最東的城市,每個人占有1個流量,總流量為2。
拆點:題中說每個城市只經過一次,因此把乙個城市看作容量為1的邊,如果西東兩個城市之間有航線,則把西城to節點連東城from節點,容量為1。為保證總流量為2,最西城邊容量和最東城容量為2。
不交叉路徑:流量為1,即可保證路徑不交叉
特判:如果最西城與最東城有航線,則邊的容量為2。
#include #include#include
#include
#include
#include
#include
#include
using
namespace
std;
//#define test
#define inf 0x3f3f3f3f
#define loop(i,n) for(int i=1; i<=n; i++)
const
int max_city = 110, max_edge = max_city*max_city + max_city * 2, max_node = max_city * 2
;map
loc;
string
cities[max_city];
bool
vis[max_city];
inttotcity, totline;
struct
mcmf
};struct
edge
};node _nodes[max_node];
edge *_edges[max_edge];
int _vcount = 0, _ecount = 0
; node *start, *sink;
inttotflow, totcost;
void reset(int n, int sid, int
tid)
edge* addedge(node *from, node *to, int cap, int
cost)
void build(int uid, int vid, int cap, int
cost)
bool
spfa()}}
}return sink->prev;
}void
proceed()
#ifdef test
printf(
"totflow %d totcost %d\n
", totflow, totcost);
#endif
} }
intgetflow()
intgetcost()
}g;void
print1()}}
}void print2(int
id) vis[id] = true
; mcmf::node *cur = id + totcity +g._nodes;
for (mcmf::edge *e = cur->head; e; e = e->next)
}cout
<< cities[id] <}int
main()
loop(line, totline)
g.proceed();
if (g.totflow<2
)
printf(
"%d\n
", -g.totcost-2
); loop(v, g._vcount)
g._nodes[v].inq = false
; print1();
print2(1);
return0;
}
luogu2770 航空路線問題
前置技能 hdu3376 matrix again 所以看到這個題,我們也會想著用最大費用最大流解決,因為從起點飛到終點再飛回來,就等於從起點飛兩次到終點且這兩次飛行除了起點終點之外沒有訪問超過一次的點。考慮拆點限流,除起點終點以外的點容量是1 花費代表邊權 起點終點容量是2。輸出方案的話,我是df...
luogu P2770 航空路線問題
傳送門 題意是選出兩條從左往右的中間點不能重複選的路徑,並使得經過的所有點數最大 可以考慮最大費用最大流,即把所有點拆點,入點向出點中間連容量為1,費用為1的邊,然後按照題目中的關係把左邊點的出點和右邊點的入點連容量為1,費用為0的邊 起點和終點的中間邊容量為2 源點到起點,終點到匯點連容量為2,費...
洛谷 P2770 航空路線問題
給定一張航空圖,圖中頂點代表城市,邊代表 2 城市間的直通航線。現要求找出一條滿足下述限制條件的且途經城市最多的旅行路線。1 從最西端城市出發,單向從西向東途經若干城市到達最東端城市,然後再單向從東向西飛回起點 可途經若干城市 2 除起點城市外,任何城市只能訪問 1 次。對於給定的航空圖,試設計乙個...