從左到右給你n個點,有m條邊連線這些點,問從最左邊的點到達最右邊的點再回到最左邊的點最多可以經過幾個點(除了起點外每個點最多只能被經過一次)。
首先,我們可以把題意轉化成從最左邊的點走兩條不相交的路線到達最右邊的點,且使經過的點最多。標程是最大費用最大流。
為了限流,我們把每個點i拆成兩個點xi,yi,x1->y1、xn->yn連一條容量為2,費用為1的邊,其他點xi->yi連一條容量為1,費用為1的邊。若有i->j可達(ii->xj最後求x1->yn的最大費用最大流即可。若最大流等於2,則有解,為最大費用-2(因為起點和終點重複計算了);否則無解。
然而,其實這題還有另一種解法!!!
我們設dpi,j表示兩條路線分別走到了i點和j點。且只往》max(i,j)的點轉移。
有同學可能會問:那如果i
其實完全不用擔心這個問題,因為(i+1,j)這個狀態可以由(i+1,j-x)的狀態轉移過來。
我們可以這麼想,假設我們已經知道了最終答案要經過哪些點,甲和乙現在同時站在起點,對於下乙個要經過的點,若在甲的路線上,就讓甲走到該點,在乙的路線上就讓乙走到該點。所以只往最右邊的點的右邊走也是可以走出最優解的。
1 #include2 #include3 #include4 #include5 #include6#define ll long long
7#define ri register int
8using
namespace
std;
9const
int inf = 0x7ffffff;10
const
int n = 100 + 10;11
12 inline int
read()
20int n, m ; bool road[n][n] ; int
dp[n][n], pre[n][n], typ[n][n], hh[n], gg[n] ;
21 mapp ;
22 mappp ;
2324
int dfs(int x,int
y)
32if
(road[i][y]) 35}
36if(!dp[x][y]) return -inf ;
37return
dp[x][y] ;38}
39int tot = 0;40
void dfss(int x,int
y) 48
if(dp[x][i] == dp[x][y]-1 &&road[i][y]) 51}
52}5354
55int
main()
60for(int i=1;i<=m;i++)
67dfs(n,n) ;
68if(!dp[n][n])
69 printf("
%d\n
",dp[n][n]) ;
70for(int i=1;iif(dp[i][n] == dp[n][n]-1)
71 sort(hh+1,hh+tot+1) ; sort(gg+1,gg+tot+1
) ;72
int sz1 = unique(hh+1,hh+tot+1) - (hh+1
) ;73
int sz2 = unique(gg+1,gg+tot+1) - (gg+1
) ;74 cout<1]<<"\n"
;75for(int i=1;i<=sz1;i++) if(hh[i] > 1) cout<"\n"
;76for(int i=sz2;i;i--) if(gg[i] > 1) cout<"
\n" ; cout<1]<<"\n"
;77return0;
78 }
題解 航空路線問題
乙個點有兩種用法,但是只能選一種用,直接把乙個點拆掉並且連一條容量為1的邊就成功限制。將乙個點拆為兩個點,乙個入點乙個出點,入點到出點連一條費用為 inf 的邊,跑費用流,最終答案就是 dfrac 輸出方案隨便弄一下就好了。注意考慮邊界情況!1 n 不連通 費用流不能跑負環。spfa能跑什麼費用流就...
航空路線 題解
一道既可以dp又可以網路流的題 戳首先為了儲存狀態,最容易想到的就是狀態壓縮,但是資料範圍不允許我們壓縮,所以就要換思路。最簡單的,就會想到,我們並不關心狀態是什麼,而關心的是狀態是否合法。我們只要讓當前這個dp是合法的,他的轉移是合法的,他的轉移又不會影響到他已經合法的狀態,那麼這樣就可以了。那麼...
luogu P2770 航空路線問題
傳送門 題意是選出兩條從左往右的中間點不能重複選的路徑,並使得經過的所有點數最大 可以考慮最大費用最大流,即把所有點拆點,入點向出點中間連容量為1,費用為1的邊,然後按照題目中的關係把左邊點的出點和右邊點的入點連容量為1,費用為0的邊 起點和終點的中間邊容量為2 源點到起點,終點到匯點連容量為2,費...