乙個點有兩種用法,但是只能選一種用,直接把乙個點拆掉並且連一條容量為1的邊就成功限制。
將乙個點拆為兩個點,乙個入點乙個出點,入點到出點連一條費用為\(-inf\) 的邊,跑費用流,最終答案就是
\[-\dfrac
\]輸出方案隨便弄一下就好了。注意考慮邊界情況!!!(1-》n),(不連通)
費用流不能跑負環。spfa能跑什麼費用流就可以跑什麼。
//@winlere
#include#include#include#include#include#include#includeusing namespace std; typedef long long ll;
inline int qr()
struct e
e(const int&a,const int&b,const int&cx,const int&d)
}e[30005];
int head[404];
int cnt=1;
inline void add(const int&fr,const int&to,const int&w,const int&c,const bool&f)
const int maxn=505;
int d[maxn];
int fl[maxn];
int in[maxn];
int last[maxn];
int s,t,n,v,cost;
const int inf=0x3f3f3f3;
const int littleinf=1;
queue < int > q;
void mincost()}}
if(fl[t]<=0)return;
cost-=fl[t]*d[t];
for(register int t=t;t!=s;t=e[last[t]^1].to)
e[last[t]].w-=fl[t],e[last[t]^1].w+=fl[t];
}}vector < int > ve,ve;
map < string , int > name;
map < int , string > arc;
int main()
for(register int t=1;t<=v;++t)
s=1;
t=n+n+2;
add(n+n+1,t,2,0,1);
add(s,2,2,0,1);
mincost();
if(e[cnt].w!=2) return puts("no solution!"),0;
printf("%d\n",cost);
int now=1;
ve.push_back(now);
while(now!=n)
}in[now]=1;
ve.push_back(now);
}in[n]=0;
now=1;
while(now!=n)
}if(now==n||f)break;
in[now]=1;
ve.push_back(now);
}reverse(ve.begin(),ve.end());
ve.push_back(1);
for(vector< int >::iterator t=ve.begin();t!=ve.end();++t) cout<::iterator t=ve.begin();t!=ve.end();++t) cout
}
航空路線 題解
一道既可以dp又可以網路流的題 戳首先為了儲存狀態,最容易想到的就是狀態壓縮,但是資料範圍不允許我們壓縮,所以就要換思路。最簡單的,就會想到,我們並不關心狀態是什麼,而關心的是狀態是否合法。我們只要讓當前這個dp是合法的,他的轉移是合法的,他的轉移又不會影響到他已經合法的狀態,那麼這樣就可以了。那麼...
網路流24題 航空路線問題 題解
從西向東依次給出 n 座城市,和這 n 座城市中的 m 條邊,求出滿足下列條件的旅行路徑 從這道題的題面再結合範圍非常有限的 n 很容易想到可以用網路流來解決。那麼下面考慮如何建圖 首先由於每乙個點只能被經過一次,那我們可以用到乙個非常常見的手法,就是拆點,將 i 拆成 i 和 i n 兩個點,再在...
航空路線問題(dp解法)
從左到右給你n個點,有m條邊連線這些點,問從最左邊的點到達最右邊的點再回到最左邊的點最多可以經過幾個點 除了起點外每個點最多只能被經過一次 首先,我們可以把題意轉化成從最左邊的點走兩條不相交的路線到達最右邊的點,且使經過的點最多。標程是最大費用最大流。為了限流,我們把每個點i拆成兩個點xi,yi,x...